如何解析 Prometheus 数据

Posted

技术标签:

【中文标题】如何解析 Prometheus 数据【英文标题】:How to parse Prometheus data 【发布时间】:2021-03-30 22:35:08 【问题描述】:

我已经能够通过如下方式发送 HTTP GET 来获取指标:

# TYPE net_conntrack_dialer_conn_attempted_total untyped net_conntrack_dialer_conn_attempted_totaldialer_name="federate",instance="localhost:9090",job="prometheus" 1 1608520832877

现在我需要解析这些数据并获得对每条数据的控制权,以便我可以转换像 json 这样的 tand 格式。

我一直在研究 Go 中的 ebnf 包: ebnf package

有人能给我指出解析上述数据的正确方向吗?

【问题讨论】:

【参考方案1】:

Prometheus's Authors 已经有一个很好的包可以做到这一点。

他们编写了一堆在 Prometheus 组件和库之间共享的 Go 库。它们被认为是 Prometheus 内部的,但您可以使用它们。

参考:github.com/prometheus/common 文档。有一个名为 expfmt 的包可以对 Prometheus 的 Exposition Format (Link) 进行解码和编码。是的,它遵循 EBNF 语法,因此也可以使用 ebnf 包,但您会立即获得 expfmt

使用的包:expfmt

示例输入:

# HELP net_conntrack_dialer_conn_attempted_total
# TYPE net_conntrack_dialer_conn_attempted_total untyped
net_conntrack_dialer_conn_attempted_totaldialer_name="federate",instance="localhost:9090",job="prometheus" 1 1608520832877

示例程序:

package main

import (
    "flag"
    "fmt"
    "log"
    "os"

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

func fatal(err error) 
    if err != nil 
        log.Fatalln(err)
    


func parseMF(path string) (map[string]*dto.MetricFamily, error) 
    reader, err := os.Open(path)
    if err != nil 
        return nil, err
    

    var parser expfmt.TextParser
    mf, err := parser.TextToMetricFamilies(reader)
    if err != nil 
        return nil, err
    
    return mf, nil


func main() 
    f := flag.String("f", "", "set filepath")
    flag.Parse()

    mf, err := parseMF(*f)
    fatal(err)

    for k, v := range mf 
        fmt.Println("KEY: ", k)
        fmt.Println("VAL: ", v)
    

样本输出:

KEY:  net_conntrack_dialer_conn_attempted_total
VAL:  name:"net_conntrack_dialer_conn_attempted_total" type:UNTYPED metric:<label:<name:"dialer_name" value:"federate" > label:<name:"instance" value:"localhost:9090" > label:<name:"job" value:"prometheus" > untyped:<value:1 > timestamp_ms:1608520832877 >

因此,expfmt 是您的用例的不错选择。

更新:OP 发布的输入中的格式问题:

参考:

    https://github.com/prometheus/pushgateway/issues/147#issuecomment-368215305

    https://github.com/prometheus/pushgateway#command-line

Note that in the text protocol, each line has to end with a line-feed
character (aka 'LF' or '\n'). Ending a line in other ways, e.g. with 
'CR' aka '\r', 'CRLF' aka '\r\n', or just the end of the packet, will
result in a protocol error.

但从错误消息中,我可以看到 \r char 存在于 put 中,这是设计不可接受的。所以使用\n作为行尾。

【讨论】:

你一定是做错了什么。通过构建它来运行这个程序 (go build)。假设可执行文件的名称是promfmt,然后运行./promfmt --f /path/to/file,其中/path/to/file 是路径(绝对或相对;两者都有效!) 在文件末尾添加一个换行符。实际上,指标后面有一个换行符。 您发布的文件有一些格式错误。尝试使用我用作输入的文件。 我已经更新了我的答案。这应该有帮助! 脚本不应该忽略以 # 开头的行吗?一旦我删除了所有以 # 开头的行,并使用答案中的更新代码,错误变为“预期整数作为时间戳,得到“1608520832877\r”

以上是关于如何解析 Prometheus 数据的主要内容,如果未能解决你的问题,请参考以下文章

与 Redis 和 Prometheus 集成

zabbix 集成 prometheus 数据

如何标记 Prometheus blackbox_exporter 端点

14Docker监控方案(Prometheus+cAdvisor+Grafana)

升级到 Spring Boot 2 后,如何向 prometheus 公开缓存指标?

开箱即用的 Prometheus 告警规则集