Spring Boot (Maven) and New Relic

Microservices and Spring Boot go hand in hand. We do need some performance monitoring to ensure that the business logic in our application does not suffer from a incorrect or devious implementation. New relic is product/service that enables developers to keep track of what is happening performance wise in their app in real-time. In this post I will show you how I managed to combine Spring Boot and New Relic.

This post is heavily inspired by this article. I found it very helpful but missing some information.

Java self-installer?

If you already read some of the official documentation on the New Relic website you probably thought you could use the "self-installer", unfortunately that is not the case. We do not have a separate application server, Spring Boot provides an embedded Apache TomCat (default). This means that we need another way to provide access, a Java Agent.

Download the Java Agent

An agent?

An instrumentation agent is a class with a special method, with a predefined signature, that the JVM will invoke before the rest of the application for you to set up any instrumentation code. Generally, instrumentation is the act of transforming classes for profiling purposes: for example, we could manipulate the definition of the String class to increment a counter every time a string is created, and thus measure e.g. how many strings per second our application creates.

New relic instructions

If you have created an account but not yet installed New Relic, the Get started with Web App Monitoring page automatically appears. If you need to download the agent again: Log in to New Relic. From the New Relic menu bar, select (account) > Account settings. Download the agent for your platform.

As you can see I downloaded the most recent version (at the time of writing this post, 3.24.0). Extract the content of the zip on your place of preference.

POM file configuration

Dependency

<dependency>  
    <groupId>com.newrelic.agent.java</groupId>
    <artifactId>newrelic-agent</artifactId>
    <version>3.24.0</version>
    <scope>provided</scope>
</dependency>  

The scope of this dependency is "provided" because our Java Agent will provide it for us.

Note: I am using version 3.24.0 here! Replace this by your version.

Dependency plugin

Only declaring the dependency is not enough, we need to actually unpack the dependency to have all necessary classes in our final uber-jar:

<plugin>  
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.10</version>
  <executions>
    <execution>
      <phase>prepare-package</phase>
      <goals>
         <goal>unpack-dependencies</goal>
      </goals>
      <configuration>
        <includeArtifactIds>newrelic-agent</includeArtifactIds>
        <outputDirectory>${project.build.outputDirectory}</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>  

Maven jar plugin

For a Java agent to run, it needs to define a Premain-Class and permissions, the premain-class is the class in the agent specifying the premain() method, similar to a regular main() method. In case of New Relic it's also important to include Can-Redefine-Classes and Can-Retransform-Classes attributes:

<plugin>  
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.5</version>
  <configuration>
    <archive>
      <manifestEntries>
        <Premain-Class>com.newrelic.bootstrap.BootstrapAgent</Premain-Class>
        <Can-Redefine-Classes>true</Can-Redefine-Classes>
        <Can-Retransform-Classes>true</Can-Retransform-Classes>
      </manifestEntries>
    </archive>
  </configuration>
</plugin>  

Multiple main() methods

You now have the New Relic agent and our own code, both contain a main() method. You have to specify the "correct" one in the "spring-boot-maven-plugin" or your build will fail:

<plugin>  
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <mainClass>my.custom.Application</mainClass>
    </configuration>
</plugin>  

Running your application

You can now start your application by executing the following command in a prompt in the New Relic directory:

java -javaagent:newrelic.jar -jar ...\target\your-application.jar  

You should now be able to monitor the performance of your application on the new relic website.