从文件中解析普罗米修斯指标并更新计数器

Posted

技术标签:

【中文标题】从文件中解析普罗米修斯指标并更新计数器【英文标题】:Parsing prometheus metrics from file and updating counters 【发布时间】:2021-04-17 07:46:52 【问题描述】:

我有一个按批次定期运行的 go 应用程序。每次运行时,它都应该从文件中读取一些 prometheus 指标,运行其逻辑,更新成功/失败计数器,并将指标写回文件。

通过查看How to parse Prometheus data 和godocs for prometheus,我能够读取文件,但我不知道如何使用expfmt.ExtractSamples() 返回的值更新app_processed_total

这是我到目前为止所做的。有人可以告诉我应该如何从这里开始吗?如何将我输入的 Vector 类型转换为 CounterVec

package main

import (
    "fmt"
    "net/http"
    "strings"
    "time"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
    dto "github.com/prometheus/client_model/go"
    "github.com/prometheus/common/expfmt"
    "github.com/prometheus/common/model"
)

var (
    fileOnDisk     = prometheus.NewRegistry()
    processedTotal = prometheus.NewCounterVec(prometheus.CounterOpts
        Name: "app_processed_total",
        Help: "Number of times ran",
    , []string"status")
)

func doInit() 
    prometheus.MustRegister(processedTotal)


func recordMetrics() 
    go func() 
        for 
            processedTotal.With(prometheus.Labels"status": "ok").Inc()
            time.Sleep(5 * time.Second)
        
    ()


func readExistingMetrics() 
    var parser expfmt.TextParser
    text := `
# HELP app_processed_total Number of times ran
# TYPE app_processed_total counter
app_processed_totalstatus="ok" 300
`
    parseText := func() ([]*dto.MetricFamily, error) 
        parsed, err := parser.TextToMetricFamilies(strings.NewReader(text))
        if err != nil 
            return nil, err
        
        var result []*dto.MetricFamily
        for _, mf := range parsed 
            result = append(result, mf)

        
        return result, nil
    

    gatherers := prometheus.Gatherers
        fileOnDisk,
        prometheus.GathererFunc(parseText),
    

    gathering, err := gatherers.Gather()
    if err != nil 
        fmt.Println(err)
    

    fmt.Println("gathering: ", gathering)
    for _, g := range gathering 
        vector, err := expfmt.ExtractSamples(&expfmt.DecodeOptions
            Timestamp: model.Now(),
        , g)

        fmt.Println("vector: ", vector)
        if err != nil 
            fmt.Println(err)
        

        // How can I update processedTotal with this new value?
    



func main() 
    doInit()
    readExistingMetrics()
    recordMetrics()

    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe("localhost:2112", nil)

【问题讨论】:

【参考方案1】:

我相信你需要使用processedTotal.WithLabelValues("ok").Inc() 或类似的东西。

更完整的例子在这里

func ExampleCounterVec() 
    httpReqs := prometheus.NewCounterVec(
        prometheus.CounterOpts
            Name: "http_requests_total",
            Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
        ,
        []string"code", "method",
    )
    prometheus.MustRegister(httpReqs)

    httpReqs.WithLabelValues("404", "POST").Add(42)

    // If you have to access the same set of labels very frequently, it
    // might be good to retrieve the metric only once and keep a handle to
    // it. But beware of deletion of that metric, see below!
    m := httpReqs.WithLabelValues("200", "GET")
    for i := 0; i < 1000000; i++ 
        m.Inc()
    
    // Delete a metric from the vector. If you have previously kept a handle
    // to that metric (as above), future updates via that handle will go
    // unseen (even if you re-create a metric with the same label set
    // later).
    httpReqs.DeleteLabelValues("200", "GET")
    // Same thing with the more verbose Labels syntax.
    httpReqs.Delete(prometheus.Labels"method": "GET", "code": "200")

本文摘自 Github 上的Promethus examples

要使用向量的值,您可以执行以下操作:

    vectorFloat, err := strconv.ParseFloat(vector[0].Value.String(), 64)
    if err != nil 
        panic(err)
    

    processedTotal.WithLabelValues("ok").Add(vectorFloat)

这是假设您在响应中只会得到一个向量值。向量的值存储为字符串,但您可以使用 strconv.ParseFloat 方法将其转换为浮点数。

【讨论】:

有没有办法让我获得的价值进入 CounterVec?我想一种想象的方式是,如果将 CounterVec 序列化到文件中,然后将其读回。 是的你可以使用.Add方法如果你想指定一个数字来增加,存储在向量中的度量值存储为一个字符串,所以你需要做一些类型转换来得到它变成float64 接受的.Add。更新了上面的例子。 谢谢。我想在app_processed_totalstatus="ok" 的情况下,我将不得不进行一些字符串操作来拆分并从vector[0].Metric.String() 中获取度量和标签。这比我想象的要复杂得多。

以上是关于从文件中解析普罗米修斯指标并更新计数器的主要内容,如果未能解决你的问题,请参考以下文章

从 grafana 中的计数器指标计算值

如何从普罗米修斯绘制每天的平均值

普罗米修斯 CollectAndCount 总是返回 1

普罗米修斯获得整数计数

从普罗米修斯抓取中排除 Kubernetes 命名空间

指标在普罗米修斯中不可见