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

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

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

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

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

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

【问题讨论】:

    标签: go prometheus amazon-cloudwatch ebnf


    【解决方案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_total{dialer_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 发布的输入中的格式问题:

    参考:

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

    2. 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”
    猜你喜欢
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多