• Prometheus系列第十篇一核心之micrometer源码分析一micrometer-registry-prometheus核心实现


    源码分析一PrometheusMeterRegistry

    • scrape方法: 按照prometheus协议标准格式处理采样点的输出
    • newCounter方法: 创建度量供用户使用
      • PrometheusMeterRegistry的容器没有Counter,则将PrometheusCounter加入collectorMap
      • 为prometheus的CollectorRegistry创建MicrometerCollector并注册
      • 通过Consumer为MicrometerCollector创建child
      • 设置child的采样读取PrometheusCounter的统计值
    • 并通过MicrometerCollector完成micrometer与prometheus的关联
    public class PrometheusMeterRegistry extends MeterRegistry {
    
        private final CollectorRegistry registry;
        /**                 -- Gauge
                            -- Histogram
         *        collector -- Summary
         *                  -- Counter
         *                  -- SimpleCollector
         *                  -()
         * 适配prometheus的collector
         */
        private final ConcurrentMap<String, MicrometerCollector> collectorMap = new ConcurrentHashMap<>();
    
        private final ExemplarSampler exemplarSampler;
    
       
        获取所有的label_value
        private static List<String> tagValues(Meter.Id id) {
            return stream(id.getTagsAsIterable().spliterator(), false).map(Tag::getValue).collect(toList());
        }
    
    
        
        按照prometheus协议标准格式处理采样点的输出
        private void scrape(Writer writer, String contentType, Enumeration<Collector.MetricFamilySamples> samples)
                throws IOException {
            TextFormat.writeFormat(contentType, writer, samples);
        }
    
    
        @Override
        public Counter newCounter(Meter.Id id) {
            根据唯一标志符创建PrometheusCounter
            PrometheusCounter counter = new PrometheusCounter(id, exemplarSampler);
            micrometer:
              - 如果PrometheusMeterRegistry的容器没有,则将PrometheusCounter加入collectorMap
              - 并且为prometheus的CollectorRegistry创建MicrometerCollector并注册
              - 通过ConsumerMicrometerCollector创建child
              - 设置child的采样读取PrometheusCounter的统计值
              - 从而完成micrometer与prometheus的关联
            prometheus:
            applyToCollector(id, new Consumer<MicrometerCollector>() {
                @Override
                public void accept(MicrometerCollector collector) {
                    List<String> tagValues = tagValues(id);
                    collector.add(tagValues,
                            new MicrometerCollector.Child() {
                                @Override
                                public Stream<MicrometerCollector.Family> samples(String conventionName, List<String> tagKeys) {
                                    return Stream.of(new MicrometerCollector.Family(Collector.Type.COUNTER, conventionName,
                                            new Collector.MetricFamilySamples.Sample(conventionName, tagKeys, tagValues,
                                                    counter.count(), counter.exemplar())));
                                }
                            });
                }
            });
            return counter;
        }
    
        @Override
        public DistributionSummary newDistributionSummary(Meter.Id id,
            ...... 删除创建实现,
            return summary;
        }
    
        @Override
        protected io.micrometer.core.instrument.Timer newTimer(Meter.Id id,
                DistributionStatisticConfig distributionStatisticConfig, PauseDetector pauseDetector) {
            ...... 删除创建实现,
            return timer;
        }
    
        @Override
        protected <T> io.micrometer.core.instrument.Gauge newGauge(Meter.Id id, @Nullable T obj,
                ToDoubleFunction<T> valueFunction) {
            ...... 删除创建实现,
            return gauge;
        }
    
        @Override
        protected LongTaskTimer newLongTaskTimer(Meter.Id id, DistributionStatisticConfig distributionStatisticConfig) {
            ...... 删除创建实现,
            return ltt;
        }
    
        Prometheus的registry
        public CollectorRegistry getPrometheusRegistry() {
            return registry;
        }
    
        private void applyToCollector(Meter.Id id, Consumer<MicrometerCollector> consumer) {
    
            collectorMap.compute(getConventionName(id), new BiFunction<String, MicrometerCollector, MicrometerCollector>() {
                @Override
                public MicrometerCollector apply(String name, MicrometerCollector existingCollector) {
    
                    if (existingCollector == null) {
                        -- collectorMap中没有相关名称的MicrometerCollector,则创建
                        MicrometerCollector micrometerCollector = new MicrometerCollector(id, PrometheusMeterRegistry.this.config().namingConvention(),
                                prometheusConfig);
                        -- 为micrometerCollector创建child,并为child设置采样数据对象
                        consumer.accept(micrometerCollector);
                        -- 完成MicrometerCollector向prometheus注册
                        return micrometerCollector.register(registry);
                    }
    
                    List<String> tagKeys = PrometheusMeterRegistry.this.getConventionTags(id).stream().map(Tag::getKey).collect(toList());
                    if (existingCollector.getTagKeys().equals(tagKeys)) {
                        consumer.accept(existingCollector);
                        return existingCollector;
                    }
    
                    return existingCollector;
                }
            });
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    源码分析一MicrometerCollector

    • 兼容prometheus设计的Collector
    • 其child采样一般读取的是micrometer本身设计的Counter等度量对象的值;[实现可以参见上文分析]
    class MicrometerCollector extends Collector implements Collector.Describable {
    
        private final Meter.Id id;
    
        private final Map<List<String>, Child> children = new ConcurrentHashMap<>();
    
        private final String conventionName;
        label值对
        private final List<String> tagKeys;
    
        private final String help;
    
        public MicrometerCollector(Meter.Id id, NamingConvention convention, PrometheusConfig config) {
            this.id = id;
            this.conventionName = id.getConventionName(convention);
            this.tagKeys = id.getConventionTags(convention).stream().map(Tag::getKey).collect(toList());
            this.help = config.descriptions() ? Optional.ofNullable(id.getDescription()).orElse(" ") : " ";
        }
    
    
        @Override
        public List<MetricFamilySamples> collect() {
            完成对外部的采集的数据暴露
            Map<String, Family> families = new HashMap<>();
    
            for (Child child : children.values()) {
                child.samples(conventionName, tagKeys).forEach(family -> {
                    families.compute(family.getConventionName(), (name, matchingFamily) -> matchingFamily != null
                            ? matchingFamily.addSamples(family.samples) : family);
                });
            }
    
            return families.values().stream()
                    .map(family -> new MetricFamilySamples(family.conventionName, family.type, help, family.samples))
                    .collect(toList());
        }
    
         
    
        interface Child {
            micrometer通过匿名内部类,在这里通过读取micrometer自身的gauge,counter的度量信息 
            Stream<Family> samples(String conventionName, List<String> tagKeys);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    总结

    • 本文介绍micrometer与prometheus的集成模块: micrometer-registry-prometheus

    • 有了集成模块后,micrometer-core定义了一系列与不同中间件结合的度量,就可以通过micrometer-registry-prometheus上报prometheus服务端

  • 相关阅读:
    服务器版博客系统、前后端交互2
    基于Spring MVC + Spring + MyBatis的【超市会员管理系统】
    17 OpenCv Canny算子
    以数智化指标管理,驱动光伏能源行业的市场推进
    Windows 10/11如何恢复永久删除的文件?
    PhalAPI学习笔记 ——— 第三章细致讲解使用PSR-4规范自定义你的命名空间
    JAVA浅谈Pair抽象类
    spring讲解笔记:spring框架学习的要点总结
    visio将形状、图形、文字、符合进行任意角度旋转(已解决)
    LuatOS-SOC接口文档(air780E)-- fskv - kv数据库,掉电不丢数据
  • 原文地址:https://blog.csdn.net/qq_35529969/article/details/126924556