Search code examples
goscopeprometheus

prometheus ConstLabels take value


I'm new to Golang and maybe my question is simple, but I've tried many ways to do this. I am trying to write a simple exporter for prometheus. My code takes a metric from the gitlab API and I want it to add only ConstLabels. My code:

func enqueueJob() {
    for {
        dat, err := getJobData()
        if err != nil {
            fmt.Println(err)
        }
        time.Sleep(10 * time.Second)
        jobsInQueues.Set(dat[0].QueuedDuration)
    }

}

var jobsInQueues = promauto.NewGauge(
    prometheus.GaugeOpts{
        Name:        "A_jobs_panding",
        Help:        "A_Jobs Pending",
        ConstLabels: prometheus.Labels{"name": dat[0].Name},
    },
)

func main() {
    enqueueJob()
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":2112", nil)
}

The question is how can I pass to jobsInQueues, dat[0].Name from the getJobData() function getJobData returns a Job struct?

type Job struct {
    ID             int      `json:"id"`
    Status         string   `json:"status"`
    Stage          string   `json:"stage"`
    Name           string   `json:"name"`
    QueuedDuration float64  `json:"queued_duration"`
    TagList        []string `json:"tag_list"`
}

If you define var dat, err = getJobData() outside of the function, it doesn't update the value of Name outside of for and I understand that


Solution

  • As the name implies, ConstLabels are a set of labels (=key-value pairs) that are present on the metric and cannot be changed. It seems you'd like to have a label where the value differs per execution.

    If so, ConstLabels is not what you're looking for. Instead, you should be looking at using a GaugeVec (gauge vector) with a label name.

    Define your metric as such:

    var jobsInQueues = promauto.NewGaugeVec(
        prometheus.GaugeOpts{
            Name: "A_jobs_panding",
            Help: "A_Jobs Pending",
        },
        []string{"name"},
    )
    

    and then, set the gauge by providing the name an value from getJobData:

    func enqueueJob() {
        for {
            dat, err := getJobData()
            if err != nil {
                fmt.Println(err)
            }
            time.Sleep(10 * time.Second)
            jobsInQueues.With(prometheus.Labels{
                "name": dat[0].Name,
            }).Set(dat[0].QueuedDuration)
        }
    
    }
    

    Note that enqueueJob is a blocking operation in your code, so it will never get around to bringing up the HTTP server. You'll want to run either the enqueueJob or http.ListenAndServe invocations on their own goroutine. Also, it's worth considering the potential distinct names returned from the Gitlab API and how they affect your metric's cardinality.