springboot读取dropwizard的metrics

autoconfig

~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/MetricsDropwizardAutoConfiguration.java

@Configuration
@ConditionalOnClass(MetricRegistry.class)
@AutoConfigureBefore(MetricRepositoryAutoConfiguration.class)
public class MetricsDropwizardAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public MetricRegistry metricRegistry() {
        return new MetricRegistry();
    }

    @Bean
    @ConditionalOnMissingBean({ DropwizardMetricServices.class, CounterService.class,
            GaugeService.class })
    public DropwizardMetricServices dropwizardMetricServices(
            MetricRegistry metricRegistry) {
        return new DropwizardMetricServices(metricRegistry);
    }

    @Bean
    public MetricReaderPublicMetrics dropwizardPublicMetrics(
            MetricRegistry metricRegistry) {
        MetricRegistryMetricReader reader = new MetricRegistryMetricReader(
                metricRegistry);
        return new MetricReaderPublicMetrics(reader);
    }

}

这里将dropwizard的metrics包装为MetricReaderPublicMetrics

MetricRegistryMetricReader

~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java

public class MetricRegistryMetricReader implements MetricReader, MetricRegistryListener {

    private static final Log logger = LogFactory.getLog(MetricRegistryMetricReader.class);

    private static final Map<Class<?>, Set<String>> numberKeys = new ConcurrentHashMap<Class<?>, Set<String>>();

    private final Object monitor = new Object();

    private final Map<String, String> names = new ConcurrentHashMap<String, String>();

    private final MultiValueMap<String, String> reverse = new LinkedMultiValueMap<String, String>();

    private final MetricRegistry registry;

    public MetricRegistryMetricReader(MetricRegistry registry) {
        this.registry = registry;
        registry.addListener(this);
    }

    @Override
    public Metric<?> findOne(String metricName) {
        String name = this.names.get(metricName);
        if (name == null) {
            return null;
        }
        com.codahale.metrics.Metric metric = this.registry.getMetrics().get(name);
        if (metric == null) {
            return null;
        }
        if (metric instanceof Counter) {
            Counter counter = (Counter) metric;
            return new Metric<Number>(metricName, counter.getCount());
        }
        if (metric instanceof Gauge) {
            Object value = ((Gauge<?>) metric).getValue();
            if (value instanceof Number) {
                return new Metric<Number>(metricName, (Number) value);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Ignoring gauge '" + name + "' (" + metric
                        + ") as its value is not a Number");
            }
            return null;
        }
        if (metric instanceof Sampling) {
            if (metricName.contains(".snapshot.")) {
                Number value = getMetric(((Sampling) metric).getSnapshot(), metricName);
                if (metric instanceof Timer) {
                    // convert back to MILLISEC
                    value = TimeUnit.MILLISECONDS.convert(value.longValue(),
                            TimeUnit.NANOSECONDS);
                }
                return new Metric<Number>(metricName, value);
            }
        }
        return new Metric<Number>(metricName, getMetric(metric, metricName));
    }

    @Override
    public Iterable<Metric<?>> findAll() {
        return new Iterable<Metric<?>>() {
            @Override
            public Iterator<Metric<?>> iterator() {
                Set<Metric<?>> metrics = new HashSet<Metric<?>>();
                for (String name : MetricRegistryMetricReader.this.names.keySet()) {
                    Metric<?> metric = findOne(name);
                    if (metric != null) {
                        metrics.add(metric);
                    }
                }
                return metrics.iterator();
            }
        };
    }

    @Override
    public long count() {
        return this.names.size();
    }

    @Override
    public void onGaugeAdded(String name, Gauge<?> gauge) {
        this.names.put(name, name);
        synchronized (this.monitor) {
            this.reverse.add(name, name);
        }
    }

    @Override
    public void onGaugeRemoved(String name) {
        remove(name);
    }

    @Override
    public void onCounterAdded(String name, Counter counter) {
        this.names.put(name, name);
        synchronized (this.monitor) {
            this.reverse.add(name, name);
        }
    }

    @Override
    public void onCounterRemoved(String name) {
        remove(name);
    }

    @Override
    public void onHistogramAdded(String name, Histogram histogram) {
        for (String key : getNumberKeys(histogram)) {
            String metricName = name + "." + key;
            this.names.put(metricName, name);
            synchronized (this.monitor) {
                this.reverse.add(name, metricName);
            }
        }
        for (String key : getNumberKeys(histogram.getSnapshot())) {
            String metricName = name + ".snapshot." + key;
            this.names.put(metricName, name);
            synchronized (this.monitor) {
                this.reverse.add(name, metricName);
            }
        }
    }

    @Override
    public void onHistogramRemoved(String name) {
        remove(name);
    }

    @Override
    public void onMeterAdded(String name, Meter meter) {
        for (String key : getNumberKeys(meter)) {
            String metricName = name + "." + key;
            this.names.put(metricName, name);
            synchronized (this.monitor) {
                this.reverse.add(name, metricName);
            }
        }
    }

    @Override
    public void onMeterRemoved(String name) {
        remove(name);
    }

    @Override
    public void onTimerAdded(String name, Timer timer) {
        for (String key : getNumberKeys(timer)) {
            String metricName = name + "." + key;
            this.names.put(metricName, name);
            synchronized (this.monitor) {
                this.reverse.add(name, metricName);
            }
        }
        for (String key : getNumberKeys(timer.getSnapshot())) {
            String metricName = name + ".snapshot." + key;
            this.names.put(metricName, name);
            synchronized (this.monitor) {
                this.reverse.add(name, metricName);
            }
        }
    }

    @Override
    public void onTimerRemoved(String name) {
        remove(name);
    }

    private void remove(String name) {
        List<String> keys;
        synchronized (this.monitor) {
            keys = this.reverse.remove(name);
        }
        if (keys != null) {
            for (String key : keys) {
                this.names.remove(name + "." + key);
            }
        }
    }

    private static Set<String> getNumberKeys(Object metric) {
        Set<String> result = numberKeys.get(metric.getClass());
        if (result == null) {
            result = new HashSet<String>();
        }
        if (result.isEmpty()) {
            for (PropertyDescriptor descriptor : BeanUtils
                    .getPropertyDescriptors(metric.getClass())) {
                if (ClassUtils.isAssignable(Number.class, descriptor.getPropertyType())) {
                    result.add(descriptor.getName());
                }
            }
            numberKeys.put(metric.getClass(), result);
        }
        return result;
    }

    private static Number getMetric(Object metric, String metricName) {
        String key = StringUtils.getFilenameExtension(metricName);
        return (Number) new BeanWrapperImpl(metric).getPropertyValue(key);
    }

}

PublicMetricsAutoConfiguration

~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfiguration.java

@Configuration
@AutoConfigureBefore(EndpointAutoConfiguration.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, CacheAutoConfiguration.class,
        MetricRepositoryAutoConfiguration.class, CacheStatisticsAutoConfiguration.class,
        IntegrationAutoConfiguration.class })
public class PublicMetricsAutoConfiguration {

    private final List<MetricReader> metricReaders;

    public PublicMetricsAutoConfiguration(
            @ExportMetricReader ObjectProvider<List<MetricReader>> metricReadersProvider) {
        this.metricReaders = metricReadersProvider.getIfAvailable();
    }

    @Bean
    public SystemPublicMetrics systemPublicMetrics() {
        return new SystemPublicMetrics();
    }

    @Bean
    public MetricReaderPublicMetrics metricReaderPublicMetrics() {
        return new MetricReaderPublicMetrics(
                new CompositeMetricReader(this.metricReaders == null ? new MetricReader[0]
                        : this.metricReaders
                                .toArray(new MetricReader[this.metricReaders.size()])));
    }

    @Bean
    @ConditionalOnBean(RichGaugeReader.class)
    public RichGaugeReaderPublicMetrics richGaugePublicMetrics(
            RichGaugeReader richGaugeReader) {
        return new RichGaugeReaderPublicMetrics(richGaugeReader);
    }

    @Configuration
    @ConditionalOnClass(DataSource.class)
    @ConditionalOnBean(DataSource.class)
    static class DataSourceMetricsConfiguration {

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(DataSourcePoolMetadataProvider.class)
        public DataSourcePublicMetrics dataSourcePublicMetrics() {
            return new DataSourcePublicMetrics();
        }

    }

    @Configuration
    @ConditionalOnClass({ Servlet.class, Tomcat.class })
    @ConditionalOnWebApplication
    static class TomcatMetricsConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public TomcatPublicMetrics tomcatPublicMetrics() {
            return new TomcatPublicMetrics();
        }

    }

    @Configuration
    @ConditionalOnClass(CacheManager.class)
    @ConditionalOnBean(CacheManager.class)
    static class CacheStatisticsConfiguration {

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(CacheStatisticsProvider.class)
        public CachePublicMetrics cachePublicMetrics() {
            return new CachePublicMetrics();
        }

    }

    @Configuration
    @ConditionalOnClass(IntegrationMBeanExporter.class)
    @ConditionalOnBean(IntegrationMBeanExporter.class)
    @ConditionalOnJava(JavaVersion.SEVEN)
    @UsesJava7
    static class IntegrationMetricsConfiguration {

        @Bean
        @ConditionalOnMissingBean(name = "springIntegrationPublicMetrics")
        public MetricReaderPublicMetrics springIntegrationPublicMetrics(
                IntegrationMBeanExporter exporter) {
            return new MetricReaderPublicMetrics(
                    new SpringIntegrationMetricReader(exporter));
        }

    }

}

这里既有SystemPublicMetrics,也有MetricReaderPublicMetrics,使用了CompositeMetricReader

MetricsEndpoint

~/.m2/repository/org/springframework/boot/spring-boot-actuator/1.4.3.RELEASE/spring-boot-actuator-1.4.3.RELEASE-sources.jar!/org/springframework/boot/actuate/endpoint/MetricsEndpoint.java

@ConfigurationProperties(prefix = "endpoints.metrics")
public class MetricsEndpoint extends AbstractEndpoint<Map<String, Object>> {

    private final List<PublicMetrics> publicMetrics;

    /**
     * Create a new {@link MetricsEndpoint} instance.
     * @param publicMetrics the metrics to expose
     */
    public MetricsEndpoint(PublicMetrics publicMetrics) {
        this(Collections.singleton(publicMetrics));
    }

    /**
     * Create a new {@link MetricsEndpoint} instance.
     * @param publicMetrics the metrics to expose. The collection will be sorted using the
     * {@link AnnotationAwareOrderComparator}.
     */
    public MetricsEndpoint(Collection<PublicMetrics> publicMetrics) {
        super("metrics");
        Assert.notNull(publicMetrics, "PublicMetrics must not be null");
        this.publicMetrics = new ArrayList<PublicMetrics>(publicMetrics);
        AnnotationAwareOrderComparator.sort(this.publicMetrics);
    }

    public void registerPublicMetrics(PublicMetrics metrics) {
        this.publicMetrics.add(metrics);
        AnnotationAwareOrderComparator.sort(this.publicMetrics);
    }

    public void unregisterPublicMetrics(PublicMetrics metrics) {
        this.publicMetrics.remove(metrics);
    }

    @Override
    public Map<String, Object> invoke() {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        List<PublicMetrics> metrics = new ArrayList<PublicMetrics>(this.publicMetrics);
        for (PublicMetrics publicMetric : metrics) {
            try {
                for (Metric<?> metric : publicMetric.metrics()) {
                    result.put(metric.getName(), metric.getValue());
                }
            }
            catch (Exception ex) {
                // Could not evaluate metrics
            }
        }
        return result;
    }

}

这里将public metric暴露在/metrics的endpoint上

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容