前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >micrometer自定义metrics

micrometer自定义metrics

作者头像
code4it
发布2018-09-17 16:05:35
2.8K0
发布2018-09-17 16:05:35
举报
文章被收录于专栏:码匠的流水账

本文主要研究下如何使用自定义micrometer的metrics

实例

DemoMetrics

代码语言:javascript
复制
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。详见源码解析部分。

验证

代码语言:javascript
复制
curl -i http://localhost:8080/actuator/metrics/demo.count

返回实例

代码语言:javascript
复制
{
  "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

代码语言:javascript
复制
@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

代码语言:javascript
复制
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

代码语言:javascript
复制
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
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码匠的流水账 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实例
    • DemoMetrics
      • 注册
        • 验证
        • 源码解析
          • MetricsAutoConfiguration
            • MeterRegistryPostProcessor
              • MeterRegistryConfigurer
              • 小结
              • doc
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档