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

时间:2021-01-12 10:58:01

标签: go prometheus

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

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

这是我迄今为止所做的。有人可以告诉我我应该如何从这里开始?如何将我输入的 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_total{status="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 个答案:

答案 0 :(得分:0)

我相信您需要使用 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 方法将其转换为浮点数。