Search code examples
javaspring-bootstatsdspring-micrometer

Configure micrometer-registry-statsd in spring boot 2


I've spent a few days and could not get it working, new to instrumentation in spring.

I have a spring boot 2 app. In pom.xml I defined:

<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-registry-statsd</artifactId>
  <version>1.1.5</version>
</dependency>

In application.conf:

management.metrics.export.statsd.host=localhost
management.metrics.export.statsd.port=8125
management.metrics.export.statsd.flavor=etsy
management.metrics.export.statsd.step=2m
management.metrics.export.statsd.enabled=true
management.endpoints.web.exposure.include=health,metrics

In the app when it starts I want to export a new metric (counter):

@SpringBootApplication
public class MyApplication {

  private static final Logger LOG = LoggerFactory.getLogger(MyApplication.class);

  private static final StatsdConfig config = new StatsdConfig() {
    @Override
    public String get(String k) { return null; }
    @Override
    public StatsdFlavor flavor() { return StatsdFlavor.ETSY; }
  };

  private static final MeterRegistry registry = new StatsdMeterRegistry(config, Clock.SYSTEM);

  public static void main(String[] args) {
    // globalRegistry is composite hence was hoping they will unite into one
    Metrics.globalRegistry.add(registry);

    Counter myCounter = Counter
        .builder("myCounter")
        .description("indicates instance count of the object")
        .tags("dev", "performance")
        .register(registry);
//      .register(Metrics.globalRegistry);

    myCounter.increment(2.0);
    LOG.info("Counter: " + myCounter.count());
    SpringApplication.run(MyApplication.class, args);
  }

}

If it is coded like above, it's not available under http://localhost:8081/actuator/metrics/myCounter. But if I uncomment .register(Metrics.globalRegistry); and comment the previous line then http://localhost:8081/actuator/metrics/myCounter contains the metric, but its value is 0.0 instead of 2.0.

What I want is to have my custom registry containing custom metrics defined across application and to be correctly registered and available under the metrics endpoint then it can be exported to StatsD. Would you know what am I missing in the above?

I followed these docs https://www.baeldung.com/micrometer and https://micrometer.io/docs/registry/statsD. How to create a bean for my code or alternatively how to use the auto-configured registry by Spring Boot?


Solution

  • Spring Boot's Micrometer auto-configuration will automatically call any MeterBinder beans to bind their meters to the auto-configured MeterRegistry. With the necessary StatsD dependencies on the classpath, which you already have, this will be a StatsD-based registry. I would recommend using this auto-configuration rather than configuring things yourself. As things stand, you will have both an auto-configured registry and your own. The auto-configured registry would back off and not be created if you exposed your registry as a Spring bean.

    I would recommend removing your StatsdConfig and StatsdMeterRegistry and using the auto-configuration instead. You can then use a MeterBinder bean to bind your counter. This will leave your application's main class looking something like this:

    @SpringBootApplication
    public class MyApplication {
    
        @Bean
        public MeterBinder exampleMeterBinder() {
            return (meterRegistry) -> Counter.builder("myCounter")
                .description("indicates instance count of the object")
                .tags("dev", "performance")
                .register(meterRegistry);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MyApplication, args);
        }
    
    }