How to parse Prometheus data
Asked Answered
F

1

14

I have been able to obtain the metrices by sending an HTTP GET as follows:

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

Now I need to parse this data and obtain control over every piece of data so that I can convert tand format like json.

I have been looking into the ebnf package in Go: ebnf package

Can somebody point me the right direction to parse the above data?

Filum answered 21/12, 2020 at 5:53 Comment(0)
H
20

There's a nice package already available to do that and it's by the Prometheus's Authors itself.

They have written a bunch of Go libraries that are shared across Prometheus components and libraries. They are considered internal to Prometheus but you can use them.

Refer: github.com/prometheus/common doc. There's a package called expfmt that can decode and encode the Prometheus's Exposition Format (Link). Yes, it follows the EBNF syntax so ebnf package could also be used but you're getting expfmt right out of the box.

Package used: expfmt

Sample Input:

# 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

Sample Program:

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)
    }
}

Sample Output:

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 >

So, expfmt is a good choice for your use-case.

Update: Formatting problem in OP's posted input:

Refer:

  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.

But from the error message, I could see \r char is present in in the put which is not acceptable by design. So use \n for line endings.

Hygrometer answered 21/12, 2020 at 7:15 Comment(6)
You must be doing something wrong. Run this program by building it (go build). Suppose the executable's name is promfmt, then run ./promfmt --f /path/to/file where /path/to/file is the path (absolute or relative; both works!)Hygrometer
Add a newline char at the end of the file. In actual, there's a newline after the metric.Hygrometer
The file you posted has some formatting errors. Try using the file I used as input.Hygrometer
I've updated my answer. That should help!Hygrometer
is the script not supposed to ignore the line that start with # ? Once i removed all the lines starting with #, and use the updated code from the answer, the error changed to " expected integer as timestamp, got "1608520832877\r"Filum
No! Why it'll ignore the #. The type of metric is mentioned in # TYPE; look at the example I shared. The problem is with the format you have. You have \r endings which Prometheus parsers don't accept. Read my answer, again!Hygrometer

© 2022 - 2024 — McMap. All rights reserved.