-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Easy way to initialize counter vecs? #190
Comments
Python and Java work the same way as Go for this. |
I have an idea how to do this quite neatly. But it's a breaking change. I'll move this issue over to the v0.10 milestone and will flesh out as soon as I find some time. |
I mostly assigned this to myself as a “default” because I used to be the maintainer of this repo. Therefore, I'm un-assigning this from myself now. New maintainers @bwplotka & @kakkoyun, please deal with this as you see fit. To get my aforementioned idea sketched out, at least vaguely (feel free to consult me for details, whoever might be working on this in the future): Labels will be managed by a new
The above all implement an interface The constructor for a httpAPIReqs := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
},
label.WithValues("method", "GET", "POST"),
label.WithIncompleteValues("code", "200", "404"),
label.New("endpoint", "/api"), // Full spec, replaces old const labels.
) // Automatically initializes children for GET/200, POST/200, GET/404, POST/404
httpAPIReqs.With(label.Set("code", "200", "method", "GET")).Inc() // Increments pre-initialized child.
httpAPIReqs.With(label.Set("code", "503", "method", "GET")).Inc() // Creates new child on the fly and increments it.
httpAPIReqs.With(label.Set("code", "200", "method", "PUT")).Inc() // Error because method="PUT" is not allowed. |
FWIW in such situations - I've found myself with a helper function to address this: // prometheusNewCounterVecZeroed creates prometheus.CounterVec with cartesian product of known labels zeroed
func prometheusNewCounterVecZeroed(opts prometheus.CounterOpts, labelNamesValues prometheusLabelNamesValues) *prometheus.CounterVec {
labelNames := make([]string, 0, len(labelNamesValues))
for i := range labelNamesValues {
labelNames = append(labelNames, i)
}
counterVec := prometheus.NewCounterVec(opts, labelNames)
indexes := make([]int, len(labelNames))
outer:
for {
labelValues := make([]string, len(labelNames))
for i := range indexes {
labelValues[i] = labelNamesValues[labelNames[i]][indexes[i]]
}
counterVec.WithLabelValues(labelValues...)
for i := range indexes {
indexes[i]++
if indexes[i] == len(labelNamesValues[labelNames[i]]) {
indexes[i] = 0
continue
}
continue outer
}
break
}
return counterVec
} It ain't pretty, is likely buggy, but makes Collector definition more readable until I discover how I "should" be doing it. |
Note that #1151 has paved the road towards auto-initialize vectors that have only constrained labels. |
It seems the Created Timestamp feature can avoid the need of knowing the label values in advance and creating custom logic like above. Created timestamp is produced on the first occurance of label for *Vec or metric. With this Prometheus (for now behind the Feedback welcome, but I think CT might close this issue and need. |
See code like https://github.com/prometheus/prometheus/blob/b0adfea8d5e883cbab5c7e4113f8ea91f7cbc099/rules/manager.go#L75-L78 .
If you know in advance all the values each label can take, it is recommended to initialize all combinations so that each possible counter is exported with zero as a value.
This could be a utility function/method or be done somehow during construction.
This is a concern not specific to
client_golang
. Other client libraries usually have the same issue.@fabxc @brian-brazil Feel free to comment…
The text was updated successfully, but these errors were encountered: