spring cloud 集成 prometheus 源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

说明

本文针对prometheus官方的spring cloud集成client
maven 依赖如下:

    <dependency>
                <groupId>io.prometheus</groupId>
                <artifactId>simpleclient_spring_boot</artifactId>
                <version>0.0.26</version>
            </dependency>

Metrics 输出

首先从metrics输出入手,http://localhost:8080/prometheus
在工程中使用注解 @EnablePrometheusEndpoint 的时候,程序启用配置,通过注册MvcEndpoint,暴露出访问路径为”prometheus”的http请求服务.
关键代码片段:
注解

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({PrometheusEndpointConfiguration.class})
    public @interface EnablePrometheusEndpoint {
    }

配置类,配置PrometheusMvcEndpoint

    @Configuration
    class PrometheusEndpointConfiguration {
        PrometheusEndpointConfiguration() {
        }

        @Bean
        public PrometheusEndpoint prometheusEndpoint() {
            return new PrometheusEndpoint(CollectorRegistry.defaultRegistry);
        }

        @Bean
        @ConditionalOnBean({PrometheusEndpoint.class})
        @ConditionalOnEnabledEndpoint("prometheus")
        public PrometheusMvcEndpoint prometheusEndpointFix(PrometheusEndpoint prometheusEndpoint) {
            return new PrometheusMvcEndpoint(prometheusEndpoint);
        }
    }

创建PrometheusEndpoint

    @ConfigurationProperties("endpoints.prometheus")
    class PrometheusEndpoint extends AbstractEndpoint<String> {
        private final CollectorRegistry collectorRegistry;

        PrometheusEndpoint(CollectorRegistry collectorRegistry) {
            super("prometheus");
            this.collectorRegistry = collectorRegistry;
        }

        public String invoke() {
            return this.writeRegistry(Collections.emptySet());
        }

        public String writeRegistry(Set<String> metricsToInclude) {
            try {
                StringWriter e = new StringWriter();
                TextFormat.write004(e, this.collectorRegistry.filteredMetricFamilySamples(metricsToInclude));
                return e.toString();
            } catch (IOException var3) {
                throw new RuntimeException("Writing metrics failed", var3);
            }
        }
    }

最终由writeRegistry输出metrics信息.
进去查看,发现实际上是将搜集器注册中心(CollectorRegistry)中所有的搜集器(Collector)中的信息, 描述到Enumeration中,再由TextFormat将Enumeration以text格式输出.

Metrics 搜集

创建搜集器时,搜集器被注册到CollectorRegistry.
创建搜集器Counter,并注册.

    public static final Counter requestTotal = Counter.build().name("NAME").labelNames("label1", "label2").help
                ("total request counter of api").register();

注册Counter:

    public C register() {
                return this.register(CollectorRegistry.defaultRegistry);
            }

            public C register(CollectorRegistry registry) {
                SimpleCollector sc = this.create();
                registry.register(sc);
                return sc;
            }

搜集器本身提供计数方法,和描述方法.
计数方法记录数据的增加, 描述方法用于输出metrics时将记录数据转换成便于描述的metrics信息.
Counter 源码:

    public class Counter extends SimpleCollector<Counter.Child> implements Describable {
        Counter(Counter.Builder b) {
            super(b);
        }

        public static Counter.Builder build(String name, String help) {
            return (Counter.Builder)((Counter.Builder)(new Counter.Builder()).name(name)).help(help);
        }

        public static Counter.Builder build() {
            return new Counter.Builder();
        }

        protected Counter.Child newChild() {
            return new Counter.Child();
        }
        //计数器加1
        public void inc() {
            this.inc(1.0D);
        }

        public void inc(double amt) {
            ((Counter.Child)this.noLabelsChild).inc(amt);
        }

        public double get() {
            return ((Counter.Child)this.noLabelsChild).get();
        }
        //将数据转换成Metric
        public List<MetricFamilySamples> collect() {
            ArrayList samples = new ArrayList(this.children.size());
            Iterator var2 = this.children.entrySet().iterator();

            while(var2.hasNext()) {
                Entry c = (Entry)var2.next();
                samples.add(new Sample(this.fullname, this.labelNames, (List)c.getKey(), ((Counter.Child)c.getValue()).get()));
            }

            return this.familySamplesList(Type.COUNTER, samples);
        }

        public List<MetricFamilySamples> describe() {
            return Collections.singletonList(new CounterMetricFamily(this.fullname, this.help, this.labelNames));
        }

        public static class Child {
            private final DoubleAdder value = new DoubleAdder();

            public Child() {
            }

            public void inc() {
                this.inc(1.0D);
            }

            public void inc(double amt) {
                if(amt < 0.0D) {
                    throw new IllegalArgumentException("Amount to increment must be non-negative.");
                } else {
                    this.value.add(amt);
                }
            }

            public double get() {
                return this.value.sum();
            }
        }

        public static class Builder extends io.prometheus.client.SimpleCollector.Builder<Counter.Builder, Counter> {
            public Builder() {
            }

            public Counter create() {
                return new Counter(this);
            }
        }
    }

来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring cloud 集成 prometheus 源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏