如何通过Micrometer的LoggingMeterRegistry实现指定格式的SpringBoot指标日志?
自定义Micrometer LoggingMeterRegistry输出格式,匹配Dropwizard风格指标日志
要让Micrometer的LoggingMeterRegistry输出你指定的Dropwizard风格指标日志,核心是重写LoggingMeterRegistry的日志输出逻辑,自定义格式化模板。以下是具体实现步骤:
1. 实现自定义LoggingMeterRegistry
继承LoggingMeterRegistry,重写log方法,按照目标格式拼接日志内容。需要根据Meter的类型(METER/COUNTER/TIMER等)提取对应的统计字段:
import io.micrometer.core.instrument.*; import io.micrometer.core.instrument.logging.LoggingMeterRegistry; import io.micrometer.core.instrument.logging.LoggingRegistryConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.time.Duration; public class DropwizardStyleLoggingMeterRegistry extends LoggingMeterRegistry { private static final Logger metricsLogger = LoggerFactory.getLogger("com.codahale.metrics.Slf4jReporter"); public DropwizardStyleLoggingMeterRegistry(LoggingRegistryConfig config) { super(config, Clock.SYSTEM); } @Override protected void log(Meter meter) { StringBuilder logLine = new StringBuilder(); Meter.Type type = meter.getType(); logLine.append("type=").append(type.name()).append(", name=").append(meter.getId().getName()); // 根据Meter类型提取对应指标字段 switch (type) { case COUNTER: Counter counter = meter.counter(); logLine.append(", count=").append(counter.count()); break; case METER: // 提取count、各时段速率值 double count = meter.measure().stream() .filter(m -> m.getStatistic() == Statistic.COUNT) .findFirst() .map(Measurement::getValue) .orElse(0.0); double meanRate = count / config.step().getSeconds(); double m1Rate = meter.measure().stream() .filter(m -> m.getStatistic() == Statistic.RATE_1_MINUTE) .findFirst() .map(Measurement::getValue) .orElse(0.0); double m5Rate = meter.measure().stream() .filter(m -> m.getStatistic() == Statistic.RATE_5_MINUTES) .findFirst() .map(Measurement::getValue) .orElse(0.0); double m15Rate = meter.measure().stream() .filter(m -> m.getStatistic() == Statistic.RATE_15_MINUTES) .findFirst() .map(Measurement::getValue) .orElse(0.0); logLine.append(", count=").append(count) .append(", mean_rate=").append(String.format("%.1f", meanRate)) .append(", m1=").append(String.format("%.1f", m1Rate)) .append(", m5=").append(String.format("%.1f", m5Rate)) .append(", m15=").append(String.format("%.1f", m15Rate)) .append(", rate_unit=events/second"); break; // 可根据业务需求扩展TIMER、GAUGE等其他类型的格式化逻辑 default: meter.measure().forEach(m -> logLine.append(", ").append(m.getStatistic().name()).append("=").append(m.getValue())); break; } // 输出符合目标格式的日志 metricsLogger.info(logLine.toString()); } }
2. 在SpringBoot中注册自定义Registry
创建配置类,将自定义的DropwizardStyleLoggingMeterRegistry注册为Spring Bean,替代默认的LoggingMeterRegistry:
import io.micrometer.core.instrument.logging.LoggingRegistryConfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.time.Duration; @Configuration public class MetricsConfig { @Bean public LoggingRegistryConfig loggingRegistryConfig() { return new LoggingRegistryConfig() { @Override public String prefix() { return "logging"; } @Override public Duration step() { // 设置指标输出间隔,默认1分钟 return Duration.ofMinutes(1); } @Override public String get(String key) { return null; } }; } @Bean public DropwizardStyleLoggingMeterRegistry dropwizardStyleLoggingMeterRegistry(LoggingRegistryConfig config) { return new DropwizardStyleLoggingMeterRegistry(config); } }
3. 配置日志框架(以Logback为例)
在logback-spring.xml中添加对应logger的配置,确保日志输出格式匹配目标模板:
<appender name="METRICS" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss,SSS} [%thread] [%level] (%logger) %msg%n</pattern> </encoder> </appender> <logger name="com.codahale.metrics.Slf4jReporter" level="INFO" additivity="false"> <appender-ref ref="METRICS"/> </logger>
效果说明
完成配置后,应用会按照你要求的格式输出指标日志,示例如下:
2024-05-20 14:30:00,123 [metrics-logger-reporter-thread-1] [INFO] (com.codahale.metrics.Slf4jReporter) type=METER, name=io.dropwizard.jetty.MutableServletContextHandler.async-timeouts, count=0, mean_rate=0.0, m1=0.0, m5=0.0, m15=0.0, rate_unit=events/second
内容的提问来源于stack exchange,提问作者userdr725
相关产品推荐
相关产品推荐

