3

Spring-Boot actuator exposes many useful metrics at /metrics such as uptime, memory usage, GC count.

Only a subset of these are sent to Graphite when using the Dropwizard Metrics integration. In specific, only the counters and gauges

Is there any way to get these other metrics to be published to graphite?

The documentation suggests that it should be possible:

Users of the Dropwizard ‘Metrics’ library will find that Spring Boot metrics are automatically published to com.codahale.metrics.MetricRegistry

Eric D
  • 303
  • 1
  • 3
  • 8
  • I had the same problem, check my answer to [Exporting Spring Boot Actuator Metrics (& Dropwizard Metrics) to Statsd](http://stackoverflow.com/questions/32215723/exporting-spring-boot-actuator-metrics-dropwizard-metrics-to-statsd) question [here](http://stackoverflow.com/questions/32215723/exporting-spring-boot-actuator-metrics-dropwizard-metrics-to-statsd/35335845#35335845).Don't want to duplicate the answer. – mxsb Feb 11 '16 at 18:40

2 Answers2

3

System Metrics created by Spring boot are not reported automatically because MetricsRegistry does not know anything about those Metrics.

You should register those metrics manually when your application boots up.

@Autowired
private SystemPublicMetrics systemPublicMetrics;

private void registerSystemMetrics(MetricRegistry metricRegistry) {
    systemPublicMetrics.metrics().forEach(m -> {
        Gauge<Long> metricGauge = () -> m.getValue().longValue();
        metricRegistry.register(m.getName(), metricGauge);   
    });
}

I have defined Gauge, not all the system metrics should be added as gauge. e.g. the Counter should be used to capture count values.

If you don't want to use Spring boot. Use can include metrics-jvm out of the box to capture JVM level metrics.

Nitin Arora
  • 2,650
  • 1
  • 26
  • 27
  • 2
    Wouldn't this going to send the same initial value repeatedly? – Eric D Jun 18 '15 at 17:51
  • No, ```systemPublicMetrics``` are updated in the background, reporter will get a different value based on the reporting interval. I have not tested this. You can test and confirm. – Nitin Arora Jun 18 '15 at 19:06
  • 1
    Pretty sure this does actually record the same value over and over. `systemPublicMetrics.metrics()` does not return a list of pointers to changing values, it returns a snapshot of the current state of the metrics and so the lambda only captures the initial value. You need to have the lambda capture `systemPublicMetrics`. – George Powell May 25 '16 at 16:04
1

Here's a solution that does update DropWizard metrics on Spring metrics change. It also does that without turning @EnableScheduling on:

@EnableMetrics
@Configuration
public class ConsoleMetricsConfig extends MetricsConfigurerAdapter {

    @Autowired
    private SystemPublicMetrics systemPublicMetrics;

    @Override
    public void configureReporters(MetricRegistry metricRegistry) {

        metricRegistry.register("jvm.memory", new MemoryUsageGaugeSet());
        metricRegistry.register("jvm.thread-states", new ThreadStatesGaugeSet());
        metricRegistry.register("jvm.garbage-collector", new GarbageCollectorMetricSet());

        metricRegistry.register("spring.boot", (MetricSet) () -> {
            final Map<String, Metric> gauges = new HashMap<String, Metric>();

            for (final org.springframework.boot.actuate.metrics.Metric<?> springMetric : 
                    systemPublicMetrics.metrics()) {

                gauges.put(springMetric.getName(), (Gauge<Object>) () -> {

                    return systemPublicMetrics.metrics().stream()
                        .filter(m -> StringUtils.equals(m.getName(), springMetric.getName()))
                        .map(m -> m.getValue())
                        .findFirst()
                        .orElse(null);

                });
            }
            return Collections.unmodifiableMap(gauges);
        });

        registerReporter(ConsoleReporter
            .forRegistry(metricRegistry)
            .convertRatesTo(TimeUnit.SECONDS)
            .convertDurationsTo(TimeUnit.MILLISECONDS)
            .build())
            .start(intervalSecs, TimeUnit.SECONDS);

    }
}

It uses the com.ryantenney.metrics library for enabling additional Spring annotations support and DropWizard reporters:

    <dependency>
        <groupId>com.ryantenney.metrics</groupId>
        <artifactId>metrics-spring</artifactId>
        <version>3.1.3</version>
    </dependency>

But it is actually not necessary in this particular case.

Sergey Shcherbakov
  • 4,534
  • 4
  • 40
  • 65