Extract Prometheus Metrics in Go

Viewed 5598

I'm new in Golang, what I am trying to do is to query Prometheus and save the query result in an object (such as a map) that has all timestamps and their values of the metric. I started from this example code with only a few changes (https://github.com/prometheus/client_golang/blob/master/api/prometheus/v1/example_test.go)

func getFromPromRange(start time.Time, end time.Time, metric string) model.Value {
    client, err := api.NewClient(api.Config{
        Address: "http://localhost:9090",
    })
    if err != nil {
        fmt.Printf("Error creating client: %v\n", err)
        os.Exit(1)
    }
    v1api := v1.NewAPI(client)
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    r := v1.Range{
        Start: start,
        End:   end,
        Step:  time.Second,
    }
    result, warnings, err := v1api.QueryRange(ctx, metric, r) 
    if err != nil {
        fmt.Printf("Error querying Prometheus: %v\n", err)
        os.Exit(1)
    }
    if len(warnings) > 0 {
        fmt.Printf("Warnings: %v\n", warnings)
    }
    fmt.Printf("Result:\n%v\n", result)

    return result
}

The result that is printed is for example: "TEST{instance="localhost:4321", job="realtime"} =>\n21 @[1597758502.337]\n22 @[1597758503.337]...

These are actually the correct values and timestamps that are on Prometheus. How can I insert these timestamps and values into a map object (or another type of object that I can then use in code)?

3 Answers

The result coming from QueryRange has the type model.Matrix.

This will then contain a pointer of type *SampleStream. As your example then contains only one SampleStream, we can access the first one directly.

The SampleStream then has a Metric and Values of type []SamplePair. What you are aiming for is the slice of sample pairs. Over this we then can iterate and build for instance a map.

mapData := make(map[model.Time]model.SampleValue)

for _, val := range result.(model.Matrix)[0].Values {
    mapData[val.Timestamp] = val.Value
}

fmt.Println(mapData)

You have to know the type of result you're getting returned. For example, model.Value can be of type Scalar, Vector, Matrix or String. Each of these types have their own way of getting the data and timestamps. For example, a Vector has an array of Sample types which contain the data you're looking for. The godocs and the github repo for the prom/go client have really great documentation if you want to dive deeper.

maybe you can find your answer in this issue

https://github.com/prometheus/client_golang/issues/194

switch {
        case val.Type() == model.ValScalar:
            scalarVal := val.(*model.Scalar)
            // handle scalar stuff
        case val.Type() == model.ValVector:
            vectorVal := val.(model.Vector)
            for _, elem := range vectorVal {
                // do something with each element in the vector
        // etc
Related