Monitor a SpringBoot application in New Relic using Micrometer

Arpan Banerjee
CodeX
Published in
6 min readMar 23, 2023

Set up your spring boot application to publish metrics using Micrometer and monitor them in New Relic

Why Micrometer?

Micrometer is a dimensional-first metrics collection facade whose aim is to allow you to time, count, and gauge your code with a vendor neutral API. Through classpath and configuration, you may select one or several monitoring systems to export your metrics data to.

Think of it like SLF4J, but for metrics!

SLF4J acts as a facade for different logging frameworks (e.g., java.util.logging, logback, Log4j). It offers an abstract logging API , making the logging independent of the actual implementation. This allows for different logging frameworks to coexist. And it helps migrate from one framework to another. Similarly, you can imagine Micrometer to acts as an interface, which bridges the gap between different metric collection frameworks like Prometheus, New Relic, Atlas, Datadog etc. Using micrometer you can swicth your monitoring systems anytime keeping your application code setup in similar fashion.

In Micrometer, you collect metrics about your application using an interface called a Meter. Meters, according to their documentation, are “created from and held in a MeterRegistry.” You can then register one or more MeterRegistry implementations to send metrics to a monitoring system, such as New Relic, Prometheus, Dynatrace, Atlas, Datadog etc. This approach decouples your metric instrumentation from the metrics backend you use, and it lets you register multiple MeterRegistry implementations to send the same metrics to multiple backends.

Let’s jump into the coding now!

From what I have learned so far. There are 3 ways to integrate New Relic with a Spring Boot Application-

  1. Using the Java Agent provided by New Relic
  2. Using New Relic’s Micrometer Dependency
  3. Micormeter’s New Relic Dependency

Micormeter’s New Relic Dependency sents metrics to New Relic as events, which is outdated now as New Relic provides its own Micrometer MeterRegistry implementation based on dimensional metrics. It provides much superior integration capabilities and is the ideal choice to go for.

For more details on this please visit the below mentioned pages.
https://micrometer.io/docs/registry/new-relic
https://newrelic.com/blog/how-to-relic/how-to-monitor-spring-boot-applications-using-micrometer-metrics

Using the Java Agent provided by New Relic

  1. Download the Java Agent from this URL- https://docs.newrelic.com/docs/release-notes/agent-release-notes/java-release-notes/
  2. Extract it.
  3. Modify the newrelic.yml file inside the extracted folder to inlcude your
    License_key:
    App_name:
  4. Create a SpringBoot application with some REST endpoints.
  5. Build the application.
  6. . Navigate to the root path where you have extracted the newrelic java agent.
  7. Enter this command
    `java -javagent:<path to your new relic jar>\newrelic.jar -jar <path to your application jar>\<you rapplication jar name>.jar`

To view the application metrics-

  1. Log in to your New Relic account.
  2. Go to Explorer Tab.
  3. Click on Services-APM
  4. You can see the name of your application(which you had mentioned in the newrelic.yml file) listed there.
  5. Click on the application name.
  6. The dashboard should look something like this.

Using New Relic’s Micrometer Dependency

This is the preferred way.

  1. Create a Spring Boot project
  2. Add these two dependencies
    <dependency>
<groupId>com.newrelic.telemetry</groupId>
<artifactId>micrometer-registry-new-relic</artifactId>
<version>0.7.0</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

3. Add this class to your project.

MicrometerConfig Class

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.newrelic.telemetry.Attributes;
import com.newrelic.telemetry.micrometer.NewRelicRegistry;
import com.newrelic.telemetry.micrometer.NewRelicRegistryConfig;

import java.time.Duration;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.util.NamedThreadFactory;

@Configuration
@AutoConfigureBefore({ CompositeMeterRegistryAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class })
@AutoConfigureAfter(MetricsAutoConfiguration.class)
@ConditionalOnClass(NewRelicRegistry.class)
public class MicrometerConfig {

@Bean
public NewRelicRegistryConfig newRelicConfig() {
return new NewRelicRegistryConfig() {
@Override
public String get(String key) {
return null;
}

@Override
public String apiKey() {
return "your_api_key"; // for production purposes take it from config file
}

@Override
public Duration step() {
return Duration.ofSeconds(5);
}

@Override
public String serviceName() {
return "your_service_name"; // for production purposes take it from config file
}

};
}

@Bean
public NewRelicRegistry newRelicMeterRegistry(NewRelicRegistryConfig config) throws UnknownHostException {
NewRelicRegistry newRelicRegistry = NewRelicRegistry.builder(config)
.commonAttributes(new Attributes().put("host", InetAddress.getLocalHost().getHostName())).build();
newRelicRegistry.config().meterFilter(MeterFilter.ignoreTags("plz_ignore_me"));
newRelicRegistry.config().meterFilter(MeterFilter.denyNameStartsWith("jvm.threads"));
newRelicRegistry.start(new NamedThreadFactory("newrelic.micrometer.registry"));
return newRelicRegistry;
}
}

4. Run the application.

As I want to record how long a method takes to execute, I will be using the Micrometer Timer metric type. A timer records the duration of an activity, and its frequency. So I will be able to see how long my method takes to execute, and how often it’s called. This is why I have used @Timed annotation in my rest endpoints. Micrometer will now calculate the execution time of the method and expose them to New Relic.

Controller Class

package springboot.micrometer.demo.controller;

import java.util.Random;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.micrometer.core.annotation.Timed;

@RestController
@RequestMapping("/rest")
public class HelloController {
Random random = new Random();

@Timed(value = "greeting1", histogram = true, percentiles = { 0.95, 0.99 }, extraTags = { "version", "1.0" })
@GetMapping("/hello")
public String hello() throws InterruptedException {
int number = random.nextInt(700 - 50) + 50;
Thread.sleep(number);
return "Hello Arpan1";
}

@Timed(value = "greeting2", histogram = true, percentiles = { 0.95, 0.99 }, extraTags = { "version", "1.0" })
@GetMapping("/hello2")
public String hello2() {
return "Hello Arpan2";
}

@Timed(value = "greeting3", histogram = true, percentiles = { 0.95, 0.99 }, extraTags = { "version", "1.0" })
@GetMapping("/hello3")
public String hello3() {
return "Hello Arpan3";
}

@GetMapping("/hello4")
public String hello4() {
return "Hello Arpan4";
}

@Timed(value = "greeting5", histogram = true, percentiles = { 0.95, 0.99 }, extraTags = { "version", "1.0" })
@GetMapping("/hello5")
public ResponseEntity<?> hello5() {
int number = random.nextInt(8 - 1) + 1;
if (number == 3) {
return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE);
}
return new ResponseEntity<>(HttpStatus.OK);
}

}

The /hello5 endpoint is designe to throw errors on random hits, so that we can view the error metrics in New Relic and set up custom alerts on it.

To view the Application metrics-

  1. Log in to your New Relic account.
  2. Go to APM & services.
  3. You can see the name of your application(which you had mentioned in the MicrometerConfig file) listed there.
  4. Click on the application name.
  5. The dashboard should look something like this.
Dashboard

This is a very basic dashboard that you get out of the box. Now you can write custom queries and built a rich dashboard of your own.

Before going away, I will show you how to see the API failures/errors.

For this-

1. Click on Data, the Metrics Explorer

2. Type in the name of the Rest endpoint which you gave in the value attribute of the @Timed annotation @Timed(value = “greeting5”)

3. Select the count metric.

4. Go to dimensions and select status. Here you can see the details of your api failures.

Setting up Alert conditions

Finally you can set up alert conditions on certain metric thresholds.

For example we can set alert conditions which will inform us if a certain API fails once within 2 minutes. Our /hello5 endpoint wil fail intermittenly so I had set up an alert on this.

This is how the alert dashboard looks like.

Alert Dashbaord

I had set up email notifications for alerts. This is how an alert mail from New Relic looks like. You can choose to get notified via slack, jira, service now incidents, mobile push etc.

Alert Email Notification

The demo spring boot application can be found here in my GitHub repo.

That’s all for this blog! Do follow me on Medium, Linkedin, and GitHub for more blogs like this!

--

--

Arpan Banerjee
CodeX
Writer for

Software Engineer III @ Walmart | Java | JavaScript | Spring | React | Docker | Linkedin : https://www.linkedin.com/in/banerjee-arpan7/