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);
}
}
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
.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With