Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exporting Metrics to files when using Spring Boot 2.0

I am looking for a way to export spring boot metrics to file in Spring Boot 2.

In Spring Boot 1.5.10, we used a Custom MetricsExporter class which implements MetricWriter and overrides set and increment methods to write the metrics using loggers. We used a log file because we have a different mechanism to process the log file later for metrics analysis.

We also used MetricsConfig class, which uses the bean MetricsEndpointMetricReader to read metrics from the metrics endpoint reader in a custom config class.

But, when we upgraded to Spring Boot 2.0.1 those are not working as there was a breaking change in the existing metrics classes.

Can someone help us with how we can export the metrics and write them using loggers when using Spring Boot 2.0?

@ExportMetricWriter
public class MetricsExporter implements MetricWriter {
  private static Logger LOGGER = LoggerFactory.getLogger("metrics");
  @Override
  public void set(Metric<?> value) {
    // Write the Gauge metrics to log file
    LOGGER.info("timestamp={}, name={}, value={}", value.getTimestamp(), value.getName(),value.getValue());
  }

  @Override
  public void increment(Delta<?> delta) {
    //Write the Counter metrics to log file
    LOGGER.info("timestamp={}, name={}, value={}", delta.getTimestamp(), delta.getName(),delta.getValue());
  }

  @Override
  public void reset(String metricName) {
    
  }
}

The MetricsConfig Class is as below:

@Configuration
public class MetricsConfig {
  //Define the MetricsExporter bean to export metrics at regular interval to a log file 
  @Bean
  public MetricsExporter metricsExporter() {
    return new MetricsExporter();
  }
  
  
  //Define the MetricsEndpointMetricReader bean to export both push(counters and gauges) and pull(public) metrics 
  @Bean
    public MetricsEndpointMetricReader metricsEndpointMetricReader(MetricsEndpoint metricsEndpoint) {
    return new MetricsEndpointMetricReader(metricsEndpoint);
    }
}
like image 572
Chuck Bartoski Avatar asked May 05 '18 19:05

Chuck Bartoski


2 Answers

You can implement a custom MeterRegistry and wire it as a @Bean. One of the roles of MeterRegistry implementations are to define the exposition format to a particular monitoring system (in your case, a log).

Here's a start:

public class LogMeterRegistry extends StepMeterRegistry {
    private final Logger logger = LoggerFactory.getLogger(LogMeterRegistry.class);

    /**
     * @param step Governs on what frequency metrics are logged
     */
    public LogMeterRegistry(Duration step) {
        super(new StepRegistryConfig() {
            @Override
            public String prefix() {
                return "log";
            }

            @Override
            public String get(String key) {
                return null;
            }

            @Override
            public Duration step() {
                return step;
            }
        }, Clock.SYSTEM);
    }

    @Override
    protected void publish() {
        for (Meter meter : getMeters()) {
            logger.info(meter.getId().toString());
            for (Measurement measurement : meter.measure()) {
                logger.info(measurement.getStatistic().toString() + "=" + measurement.getValue());
            }

        }
    }

    @Override
    protected TimeUnit getBaseTimeUnit() {
        return TimeUnit.SECONDS;
    }
}

An issue is open for Micrometer 1.1 to provide an out-of-the-box LogMeterRegistry.

like image 58
Jonathan Schneider Avatar answered Sep 21 '22 00:09

Jonathan Schneider


If you are using Spring Boot 2.x which means version of Micrometer >= 1.1.0, you could simply configure a bean like

@Bean
LoggingMeterRegistry loggingMeterRegistry() {
    return new LoggingMeterRegistry();//by default, it will log metrics every 1m
}

You can also configure a different period cycle like :

@Bean
LoggingMeterRegistry loggingMeterRegistry() {


    return new LoggingMeterRegistry(new LoggingRegistryConfig() {
        @Override
        public Duration step() {
            return Duration.ofSeconds(10); // log every 10 seconds
        }

        @Override
        public String get(String key) {
            return null;
        }
    }, Clock.SYSTEM);
}

If you don't use a higher enough spring boot version, try declare a version of 1.1.x of in micrometer-core your pom.xml

    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-core</artifactId>
        <version>1.1.3</version>
    </dependency> 
like image 34
JaskeyLam Avatar answered Sep 20 '22 00:09

JaskeyLam