micrometer自定义metrics

编程

实例

DemoMetrics

public class DemoMetrics implements MeterBinder {

AtomicInteger count = new AtomicInteger(0);

@Override

public void bindTo(MeterRegistry meterRegistry){

Gauge.builder("demo.count", count, c -> c.incrementAndGet())

.tags("host", "localhost")

.description("demo of custom meter binder")

.register(meterRegistry);

}

}

这里实现了MeterBinder接口的bindTo方法,将要采集的指标注册到MeterRegistry

注册

  • 原始方式

new DemoMetrics().bindTo(registry);

  • springboot autoconfigure

@Bean

public DemoMetrics demoMetrics(){

return new DemoMetrics();

}

在springboot只要标注下bean,注入到spring容器后,springboot会自动注册到registry。springboot已经帮你初始化了包括UptimeMetrics等一系列metrics。详见源码解析部分。

验证

curl -i http://localhost:8080/actuator/metrics/demo.count

返回实例

{

"name": "demo.count",

"measurements": [

{

"statistic": "VALUE",

"value": 6

}

],

"availableTags": [

{

"tag": "host",

"values": [

"localhost"

]

}

]

}

源码解析

MetricsAutoConfiguration

spring-boot-actuator-autoconfigure-2.0.0.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfiguration.java

@Configuration

@ConditionalOnClass(Timed.class)

@EnableConfigurationProperties(MetricsProperties.class)

@AutoConfigureBefore(CompositeMeterRegistryAutoConfiguration.class)

public class MetricsAutoConfiguration {

@Bean

@ConditionalOnMissingBean

public Clock micrometerClock(){

return Clock.SYSTEM;

}

@Bean

public static MeterRegistryPostProcessor meterRegistryPostProcessor(

ApplicationContext context){

return new MeterRegistryPostProcessor(context);

}

@Bean

@Order(0)

public PropertiesMeterFilter propertiesMeterFilter(MetricsProperties properties){

return new PropertiesMeterFilter(properties);

}

@Configuration

@ConditionalOnProperty(value = "management.metrics.binders.jvm.enabled", matchIfMissing = true)

static class JvmMeterBindersConfiguration {

@Bean

@ConditionalOnMissingBean

public JvmGcMetrics jvmGcMetrics(){

return new JvmGcMetrics();

}

@Bean

@ConditionalOnMissingBean

public JvmMemoryMetrics jvmMemoryMetrics(){

return new JvmMemoryMetrics();

}

@Bean

@ConditionalOnMissingBean

public JvmThreadMetrics jvmThreadMetrics(){

return new JvmThreadMetrics();

}

@Bean

@ConditionalOnMissingBean

public ClassLoaderMetrics classLoaderMetrics(){

return new ClassLoaderMetrics();

}

}

@Configuration

static class MeterBindersConfiguration {

@Bean

@ConditionalOnClass(name = { "ch.qos.logback.classic.LoggerContext",

"org.slf4j.LoggerFactory" })

@Conditional(LogbackLoggingCondition.class)

@ConditionalOnMissingBean(LogbackMetrics.class)

@ConditionalOnProperty(value = "management.metrics.binders.logback.enabled", matchIfMissing = true)

public LogbackMetrics logbackMetrics(){

return new LogbackMetrics();

}

@Bean

@ConditionalOnProperty(value = "management.metrics.binders.uptime.enabled", matchIfMissing = true)

@ConditionalOnMissingBean

public UptimeMetrics uptimeMetrics(){

return new UptimeMetrics();

}

@Bean

@ConditionalOnProperty(value = "management.metrics.binders.processor.enabled", matchIfMissing = true)

@ConditionalOnMissingBean

public ProcessorMetrics processorMetrics(){

return new ProcessorMetrics();

}

@Bean

@ConditionalOnProperty(name = "management.metrics.binders.files.enabled", matchIfMissing = true)

@ConditionalOnMissingBean

public FileDescriptorMetrics fileDescriptorMetrics(){

return new FileDescriptorMetrics();

}

}

static class LogbackLoggingCondition extends SpringBootCondition {

@Override

public ConditionOutcome getMatchOutcome(ConditionContext context,

AnnotatedTypeMetadata metadata){

ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();

ConditionMessage.Builder message = ConditionMessage

.forCondition("LogbackLoggingCondition");

if (loggerFactory instanceof LoggerContext) {

return ConditionOutcome.match(

message.because("ILoggerFactory is a Logback LoggerContext"));

}

return ConditionOutcome

.noMatch(message.because("ILoggerFactory is an instance of "

+ loggerFactory.getClass().getCanonicalName()));

}

}

}

可以看到这里注册了好多metrics,比如UptimeMetrics,JvmGcMetrics,ProcessorMetrics,FileDescriptorMetrics等

这里重点看使用@Bean标注了MeterRegistryPostProcessor

MeterRegistryPostProcessor

spring-boot-actuator-autoconfigure-2.0.0.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessor.java

class MeterRegistryPostProcessor implements BeanPostProcessor {

private final ApplicationContext context;

private volatile MeterRegistryConfigurer configurer;

MeterRegistryPostProcessor(ApplicationContext context) {

this.context = context;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName)

throws BeansException {

if (bean instanceof MeterRegistry) {

getConfigurer().configure((MeterRegistry) bean);

}

return bean;

}

@SuppressWarnings("unchecked")

private MeterRegistryConfigurer getConfigurer() {

if (this.configurer == null) {

this.configurer = new MeterRegistryConfigurer(beansOfType(MeterBinder.class),

beansOfType(MeterFilter.class),

(Collection<MeterRegistryCustomizer<?>>) (Object) beansOfType(

MeterRegistryCustomizer.class),

this.context.getBean(MetricsProperties.class).isUseGlobalRegistry());

}

return this.configurer;

}

private <T> Collection<T> beansOfType(Class<T> type) {

return this.context.getBeansOfType(type).values();

}

}

可以看到这里new了一个MeterRegistryConfigurer,重点注意这里使用beansOfType(MeterBinder.class)方法的返回值给其构造器

MeterRegistryConfigurer

spring-boot-actuator-autoconfigure-2.0.0.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryConfigurer.java

class MeterRegistryConfigurer {

private final Collection<MeterRegistryCustomizer<?>> customizers;

private final Collection<MeterFilter> filters;

private final Collection<MeterBinder> binders;

private final boolean addToGlobalRegistry;

MeterRegistryConfigurer(Collection<MeterBinder> binders,

Collection<MeterFilter> filters,

Collection<MeterRegistryCustomizer<?>> customizers,

boolean addToGlobalRegistry) {

this.binders = (binders != null ? binders : Collections.emptyList());

this.filters = (filters != null ? filters : Collections.emptyList());

this.customizers = (customizers != null ? customizers : Collections.emptyList());

this.addToGlobalRegistry = addToGlobalRegistry;

}

void configure(MeterRegistry registry) {

if (registry instanceof CompositeMeterRegistry) {

return;

}

// Customizers must be applied before binders, as they may add custom

// tags or alter timer or summary configuration.

customize(registry);

addFilters(registry);

addBinders(registry);

if (this.addToGlobalRegistry && registry != Metrics.globalRegistry) {

Metrics.addRegistry(registry);

}

}

@SuppressWarnings("unchecked")

private void customize(MeterRegistry registry) {

LambdaSafe.callbacks(MeterRegistryCustomizer.class, this.customizers, registry)

.withLogger(MeterRegistryConfigurer.class)

.invoke((customizer) -> customizer.customize(registry));

}

private void addFilters(MeterRegistry registry) {

this.filters.forEach(registry.config()::meterFilter);

}

private void addBinders(MeterRegistry registry) {

this.binders.forEach((binder) -> binder.bindTo(registry));

}

}

可以看到configure方法里头调用了addBinders,也就是把托管给spring容器的MeterBinder实例bindTo到meterRegistry

小结

springboot2引入的micrometer,自定义metrics只需要实现MeterBinder接口,然后托管给spring即可,springboot的autoconfigure帮你自动注册到meterRegistry。

doc

  • micrometer docs
  • https://www.cnblogs.com/duanxz/p/10179946.html

以上是 micrometer自定义metrics 的全部内容, 来源链接: utcz.com/z/516237.html

回到顶部