-1

I have scraped data from Prometheus and the response is as below. I want to get the dimension data into an array (for manipulation) using Go. Can anyone Help me please. Thank You :)

func main() {
    resp, err := http.Get("http://desktop-o1hkgm7:9090/federate?match%5B%5D=%7Bdialer_name%3D%22alertmanager%22%7D")
    if err != nil {
        log.Fatalln(err)
    }
    //We Read the response body on the line below.
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatalln(err)
    }
    //Convert the body to type string
    sb := string(body)
    log.Printf(sb)
}

The response is as below:

# TYPE net_conntrack_dialer_conn_attempted_total untyped
net_conntrack_dialer_conn_attempted_total{dialer_name="alertmanager",instance="localhost:9090",job="prometheus"} 0 1609568651186
# TYPE net_conntrack_dialer_conn_closed_total untyped
net_conntrack_dialer_conn_closed_total{dialer_name="alertmanager",instance="localhost:9090",job="prometheus"} 0 1609568651186
# TYPE net_conntrack_dialer_conn_established_total untyped
net_conntrack_dialer_conn_established_total{dialer_name="alertmanager",instance="localhost:9090",job="prometheus"} 0 1609568651186
# TYPE net_conntrack_dialer_conn_failed_total untyped
net_conntrack_dialer_conn_failed_total{dialer_name="alertmanager",instance="localhost:9090",job="prometheus",reason="refused"} 0 1609568651186
"prometheus",reason="timeout"} 0 1609568651186
net_conntrack_dialer_conn_failed_total{dialer_name="alertmanager",instance="localhost:9090",job="prometheus",reason="unknown"} 0 1609568651186

I got this value after getting key and values. Can I loop through the 'name' and 'value' inside metric? How can I do this if it is possible? I tried but displays cannot loop through MetricFamily.

Image

newbie dev
  • 161
  • 6
  • 19
  • I've answered a similar question before: https://stackoverflow.com/a/65388822/5821408 (You can modify the code and make it fit for your use case). – shmsr Jan 02 '21 at 07:06
  • Does this answer your question? [How to parse Prometheus data](https://stackoverflow.com/questions/65388098/how-to-parse-prometheus-data) – shmsr Jan 02 '21 at 07:07
  • @shmsr. Thank you for your kind reply. I want to automate it, I don't want to build everytime the program runs. Is there any other way from which i can directly get the value like you suggested. and I want to get the dimension inside the label as well. – newbie dev Jan 02 '21 at 07:21
  • Build every time? Why? You just have to change how you get the exposition format. I'm reading it from a file; and in your case, you have to get it using HTTP. – shmsr Jan 02 '21 at 09:24
  • Give it a try, it's easy. – shmsr Jan 02 '21 at 09:25
  • @shmsr. Thank You for reply :) ... I have updated the question. Can you please look into it.?? I have got key and value as you said. Is there any way to get metric in a separate way for name and value? – newbie dev Jan 02 '21 at 09:34
  • Please see my answer. And please use standard terms otherwise it's really hard to understand. I've answered on the basis of what I've understood so far. – shmsr Jan 02 '21 at 14:08
  • Also, don't post images. It's better if you paste it here directly on code block (maybe). – shmsr Jan 02 '21 at 14:11

1 Answers1

3

The OP is not very clear in explaining what he/she actually wants. The output that the OP is referring to is "Prometheus Exposition Format". This is EBNF syntax and it's better to talk in terms of metric_name, label_name, label_value, etc. instead of saying get the dimension data into an array (for manipulation).

Exposition Format:

metric_name [
  "{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `"` } [ "," ] "}"
] value [ timestamp ]

What I'm assuming is that that for every metric_name, the OP wants to loop over labels i.e, label_name, label_value.

I marked it as a duplicate because I've answered a very similar question before and to achieve the required, only minor changes are required.

In the following program, source file where the metrics are present (in exposition format) are stored in the local filesystem. So, one way to change it so that it fetches the metrics over HTTP and then loop over labels for every metric_name.

  • 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 Output:
KEY: net_conntrack_dialer_conn_attempted_total
VAL: name:"dialer_name" value:"federate"
VAL: name:"instance" value:"localhost:9090"
VAL: name:"job" value:"prometheus"

Code:

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 parseMetricFamily(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 := parseMetricFamily(*f)
    fatal(err)

    for k, v := range mf {
        fmt.Printf("KEY: %v\n", k)
        for _, m := range v.Metric {
            for _, l := range m.Label {
                fmt.Printf("VAL: %v\n", l)
            }
        }
    }
}
shmsr
  • 3,802
  • 2
  • 18
  • 29
  • Thank you for this. It's not exactly the answer i was looking for. But from this I got the idea. :). Thank you so much – newbie dev Jan 02 '21 at 14:34