• 【转】玩转PROMETHEUS(6) 实现自定义的COLLECTOR


    原文: http://vearne.cc/archives/39380

    -------------------------

    版权声明 本站原创文章 由 萌叔 发表
    转载请注明 萌叔 | http://vearne.cc
    

    1. 前言

    prometheus的官方和社区为了我们提供了丰富的exporter。对常见的硬件设备、数据库、消息队列以及常见的软件进行监控。另外官方还为我们提供了4种指标类型方便我们自定义exporter

    • Counter Counter代表累计指标,它表示单调递增的计数器,通常用于表示服务请求数,完成的任务数,错误的数量。
    • Gauge Gauge表示某种瞬时状态,某一时刻的内存使用率、消息队列中的消息数量等等。它的值既可以增大,也可以减小。
    • Histogram 通常用于top percentile,比如请求耗时的TP90、TP99等
    • Summary 类似于Histogram

    我们回顾一下prometheus的指标采集的一般过程

    1) 创建指标

    HTTPReqTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total number of HTTP requests made.",
        }, []string{"method", "path", "status"})
    

    2) 指标注册到 DefaultRegisterer

     prometheus.MustRegister(
            HTTPReqTotal,
        )
    

    3) 指标和对应的值通过HTTP API暴露出来

    The caller of the Gather method can then expose the gathered metrics in some way. Usually, the metrics are served via HTTP on the /metrics endpoint.

    http.Handle("/metrics", promhttp.Handler())
    

    当promhttp.Handler()被执行时,所有metric被序列化输出。题外话,其实输出的格式既可以是plain text,也可以是protocol Buffers。

    这里涉及一个问题,这些metric的值是什么时候采集的?

    2. 指标采集的触发时机

    CounterHistogram的触发时机比较明确
    比如: 为了监控QPS, 请求完成以后,请求数量直接+1

            HTTPReqTotal.With(prometheus.Labels{
                PromLabelMethod: "GET",
                PromLabelPath:   "/api/query",
                PromLabelStatus: "200",
            }).Inc()
    

    比如: 为了监控请求耗时分布,请求完成以后,只需

    HTTPReqDuration.With(prometheus.Labels{
                PromLabelMethod: "GET",
                PromLabelPath:   "/api/query",
            }).Observe(3.15)
    

    对于 Gauge这种瞬时值,该怎么办?
    假定我们要监控某个channel的长度

    var jobChannel chan int
    

    2.1 方法1-定时任务

    example1.go

    jobChanLength:= prometheus.NewGauge(prometheus.GaugeOpts{
            Name: "job_channel_length",
            Help: "length of job channel",
        })
    
        go func() {
            jobChanLength.Set(float64(len(jobChannel)))
            c := time.Tick(30 * time.Second)
            for range c {
                jobChanLength.Set(float64(len(jobChannel)))
            }
        }()
    

    2.2 方法2-自定义Collector

    example2.go
    实现Collector接口

    type Collector interface {
        Describe(chan<- *Desc)
        // 比如满足并发安全
        Collect(chan<- Metric) 
    }
    

    Collect is called by the Prometheus registry when collecting metrics

    当promhttp.Handler()被调用是,Collect函数被执行,所以此函数不能运行时间过长,否则可能导致promhttp.Handler()执行超时。

    type ChanCollector struct{
        JobChannel chan int
        Name string
    }
    
    func NewChanCollector(jobChannel chan int, name string) *ChanCollector{
        c := ChanCollector{}
        c.JobChannel = jobChannel
        c.Name = name
        return &c
    }
    
    func (c *ChanCollector) Describe(ch chan<- *prometheus.Desc) {
        desc := prometheus.NewDesc(c.Name, "length of channel", nil, nil)
        ch <- desc
    }
    
    func (c *ChanCollector) Collect(ch chan<- prometheus.Metric) {
        ch <- prometheus.MustNewConstMetric(
            prometheus.NewDesc(c.Name, "length of channel", nil, nil),
            prometheus.GaugeValue,
            float64(len(c.JobChannel)),
        )
    }
    
        collector := NewChanCollector(jobChannel, "job_channel_length")
        prometheus.MustRegister(collector)
    

    2.3 方法3-利用GaugeFunc实现

    example3.go

        jobChanLength := prometheus.NewGaugeFunc(prometheus.GaugeOpts{
            Name: "job_channel_length",
            Help: "length of job channel",
        },func() float64{
            return float64(len(jobChannel))
        })
    
        prometheus.MustRegister(jobChanLength)
    

    只需要定义函数 func()float64{} 即可
    当promhttp.Handler()被调用时,func()float64{} 被触发。

    3. 总结

    如果执行速度很快,直接使用方法3就可以; 但是如果执行速度很快且输出的指标很多,推荐使用方法2; 其它情况推荐使用方法1。

    参考资料

      1. EXPORTERS AND INTEGRATIONS
      2. METRIC TYPES
  • 相关阅读:
    2020年12月15日Java学习日记
    2020年12月12日Java学习日记
    2020年12月10日Java学习日记
    2020年12月8日Java学习日记
    2020年12月4日Java学习日记
    2020年12月1日Java学习日记
    2020年11月30日Java学习日记
    2020年11月27日Java学习日记
    2020年11月26日Java学习日记
    B. Navigation System【CF 1320】
  • 原文地址:https://www.cnblogs.com/oxspirt/p/14985762.html
Copyright © 2020-2023  润新知