Share:

Like this:

This post describes how I got New Relic to run with my Clojure project. I’m using Heroku but most of what I say here should be applicable in other environments and I’ll try to point you in the right direction when it doesn’t. Please, feel free to comment with improvements or corrections.

There are already a few articles out there about this same subject but none of them gave me a complete picture, which is what I’m attempting here. I’ll cite my references at the end.

Enabling New Relic

There are two ways to enable New Relic in a Heroku app. One is through a command like this one:

heroku addons:create newrelic:wayne

The other way is through the dashboard of the app in question. It doesn’t matter which way you use, but after enabling it, your dashboard should have an entry for New Relic, like this:

Click on “New Relic APM :: Newrelic”, which will take you to your New Relic welcome screen (unless you already have projects). If you are not using Heroku, creating a New Relic account will land you at a similar-looking page:

Click on APM – that’s Application Performance Management, i.e. what most people have in mind when they say “New Relic”. That will take you to the page in which you choose which programming language or framework you are using:

Sadly, no Clojure, so just click on Java.

If you already have a New Relic project, to create a new one, search for the “Add More” link:

Once you click on Java, you’ll see the instructions to install the Java agent in a Java project:

In the rest of this post I’ll explain how to get the Java agent running in a Clojure project. But first, the configuration.

Configuration

New Relic has a licence key that your app will use to both identify and authenticate itself. If you scroll down you’ll see a button to reveal that key:

On that page click “Download the Java agent”. It’s a zip file containing some documentation, a bunch of jar files, and the one file you care about: newrelic.yml. Copy that file to the root of your Clojure project.

In that file, you’ll find the licence key specified in a line like this:

license_key: 'bab654434b8672dc0580ab7f88bf9c7984dd81bd'

Having credentials in your source code repository is a bad idea. Your app should be able to be open source without your server and services being compromised. Even if your app is not open source, you may get developers and designers that you don’t trust working on it or you might use third party services to run tests, perform static analysis, etc, etc. that you don’t want to have the keys of your kingdom.

Remove the licence so that that line looks like this:

license_key: ''

and instead make sure you export an environment variable named NEW_RELIC_LICENSE_KEY that will be automatically picked up by New Relic to authenticate to their server:

NEW_RELIC_LICENSE_KEY="bab654434b8672dc0580ab7f88bf9c7984dd81bd"

Heroku sets this up automatically when you add the plug-in, and you can see this environment variable in your applications settings:

Another alternative would be to provision the servers with a full copy of newrelic.yml, an approach I use when deploying Rails applications with Capistrano but I’ve never used it with a Clojure or Java application.

In the config file, also search for the lines defining the name of your application:

and replace all mentions of “My Application” with the proper name of your application. Leave the extra bits between parenthesis as it is, so you can identify whether a report or alert is referring to production, staging or something else.

Java Agent

New Relic for Java runs as a Java agent. You can learn more about them in the java.lang.instrument documentation but in short, they are jars that are loaded by the JVM independently and around your own application. Leiningen has support for Java Agents by adding:

New Relic is being loaded and it’s complaining about the lack of a key. That’s a good thing.

When you deploy to production, things won’t go as smooth. Java won’t be able to find the newrelic-agent.jar in the CLASSPATH so it’ll just silently skip the agent. There’s a command line for java that will help it locate the jar: -javaagent:newrelic-agent.jar. The problem with that is, where’s the jar? Nowhere to be seen.

The official recommendation from New Relic and other blog posts is to copy the jar file to your source tree and then reference it from there. That has two problems:

Having big blobs in source control is not very nice.

That jar is out of the loop of dependencies, so it won’t ever be upgraded unless someone remembers to explicitly do it. That’s bad.

To solve this problem I created a library called jar-copier that copies a Java agent jar into a configured directory so that you can point to it with the command line. This works in Heroku because when you deploy, the source code is checked out from git and then the uberjar is built on that same server, so jar-copier has an opportunity to run and place the jar in the correct place.

If you are shipping ready-made uberjars, you’ll have to find another way to provision your server with a copy of the agent jar in a well known location that you can point to (or that’s in the CLASSPATH ).

jar-copier is a Leiningen plug-in, so you need to add it to your list of plug-ins like this:

:plugins [; other plugins
[com.carouselapps/jar-copier "0.2.0"]]

then, to make sure it’s run automatically, your project needs:

:prep-tasks ["javac" "compile" "jar-copier"]

and finally, you need to configure jar-copier to copy Java agents and know the destination, for example:

Reporting data

By this point, the Java agent is running and possibly reporting some data, but you are not instrumenting your code. I found a bunch of libraries that you can use to instrument your code and by far my favorite is new-reliquary because it provides Ring middleware.

At the time of this writing, the released version, 0.1.5, doesn’t support reporting data as a web transaction. New Relic will categorize the data as Non-Web, which is not what you want. Thankfully there’s already a pull request to fix this and we released it as com.carouselapps/new-reliquary 0.1.5. We are likely to request it to be deleted once it’s released properly, but until then, feel free to use our copy.

After adding it to your project, you need to add the Ring middleware. In the file where you set up your middleware add the following requires:

which doesn’t enable New Relic in development. Yours is probably quite different though. And that’s it, you should now be seeing your performance reports in New Relic. You can see a full example in proclodo-spa-server-rendering’s

Shameless plug time! At Carousel Apps we not only use New Relic, we have a constant dashboard displaying it so we never lose sight of our current performance and servers. We’ve created a product to display dashboards like this called Screensaver Ninja. It displays websites, including New Relic, as your screensaver, so you can turn all your computers into information disseminators. It’s also great for permanent screens, as it displays many web sites in rotation, keeping them fresh (useful even for self updating websites, like New Relic, because sometimes they crash) as well as keeping the computer secure by using the screensaver lock.

My References

In the process of getting New Relic to work with Clojure running on Heroku, I found the following blog posts:

Share:

Like this:

jar-copier is a Leiningen plug in to copy jars from your dependencies to your source tree. It’s a very small simple utility that proved to be necessary to have a sane setup with Java agents (New Relic for example).

It’s very simple to use. Put [jar-copier “0.1.0”] into the :plugins vector on your project.clj. To run this plug in, execute:

$ lein jar-copier

If you want the task to run automatically, which is recommended, add:

:prep-tasks ["javac" "compile" "jar-copier"]

and it’ll be invoked every time you build your uberjar.

You need to configure the plug-in in your project.clj like this:

:jar-copier {:java-agents true
:destination "resources/jars"}

:java-agents instruct this plug in to automatically copy any jars that are specified as Java agents. :destination specifies where to copy them to.