-
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
Go metrics go_memstats_alloc_bytes and go_memstats_alloc_bytes_total collide in OpenMetrics and are still both exposed #829
Comments
Your issue here is that you tried to parse Prometheus text format with the OpenMetrics parser, so there is no bug here. However, one of these will need a rename when client_golang gains full OpenMetrics support in a future version. |
🤔 My impression was that setting the Looks like the python client isn't relevant to this issue - seems the Go parser behaves the same way: Here's some test code that demonstrates the issue: package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/expfmt"
)
func main() {
h := promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer,
promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{EnableOpenMetrics: true}),
)
srv := httptest.NewServer(h)
defer srv.Close()
req, _ := http.NewRequest(http.MethodGet, srv.URL, nil)
req.Header.Set("Accept", "application/openmetrics-text; version=0.0.1")
resp, _ := srv.Client().Do(req)
fmt.Printf("%s %d\n", resp.Proto, resp.StatusCode)
fmt.Printf("Header:\n")
for k, v := range resp.Header {
fmt.Printf("\t%s: %v\n", k, v)
}
parser := &expfmt.TextParser{}
_, err := parser.TextToMetricFamilies(resp.Body)
if err != nil {
panic(err)
}
} When I run I see: $ go run .
HTTP/1.1 200
Header:
Content-Type: [application/openmetrics-text; version=0.0.1; charset=utf-8]
Date: [Wed, 30 Dec 2020 16:26:08 GMT]
panic: text format parsing error in line 19: second HELP line for metric name "go_memstats_alloc_bytes"
goroutine 1 [running]:
main.main()
/Users/hairyhenderson/go/src/github.com/hairyhenderson/temp/main.go:34 +0x5d1
exit status 2
My impression based on the above is that even the partial OpenMetrics support present now is incompatible with the output that the Go collector produces... I'm confused now about how this works when Prometheus scrapes this output - though perhaps it doesn't use |
That code example is using the Prometheus text format parser with OpenMetrics input, which can also run into issues. This still doesn't indicate a bug, as you're conflating the two formats. |
While your examples don't directly demonstrate it, there is an issue there in the OpenMetrics output:
as there's a repeated metric family name. |
Ah - I think I follow... Is there a Go equivalent for the python Also, to answer my earlier confusion about how Promtheus itself works - it has its own parser which doesn't seem to care about duplicate names.
Isn't that why the error That seems to be caused by https://github.com/prometheus/common/blob/master/expfmt/openmetrics_create.go#L92, where the |
Yes. A full Go OpenMetrics parser has yet to be written.
Kinda, trying to parse one format as another format isn't exactly wise and something else may break instead. The original report would have failed for other reasons for example, as typical Prometheus format output is not valid OpenMetrics output.. |
Parser shenanigans aside, the actual issue here is that the standard metrics exposed by the Go collector are fine with the old Prometheus formats, but run into a known issue with OpenMetrics: Since OpenMetrics shaves off the For full OpenMetrics support, we need to change the metric name. But what to do right now? The current preliminary OpenMetrics implementation serves invalid OpenMetrics format. Interestingly, Prometheus is "fine" with it: It ingests both metrics. For the metadata API, it drops the gauge and keeps the counter (which I guess is just because the counter comes later in the exposition and overrides the gauge). We could just leave things as is, accepting that the OpenMetrics format exposed is technically invalid (while Prometheus currently handles it in a way that at least doesn't break anyone when activating OpenMetrics). Or we could fix the format by either not exposing one of the metrics or by renaming one of the metrics whenever OpenMetrics is negotiated. However, this would break everyone that relies on the metrics as they are now. |
We could for now always expose counters as unknown for OM, or being smarter about when we have them as counters rather than unknown. |
It made me quite happy that finally tools like Grafana start to make use of metadata in tooltips etc. Obfuscating counters as unknown is not ideal for them. |
There is the option of only to switching to unknown if there is a collision. |
Yes, that's what I had in mind. It's still not ideal… 😞 |
Yeah, but I think it's the best we can do currently. We might also want to decide on a new name for one of the metrics now and implement it as a duplicate, as that'll make the future transition easier. alloc->allocated maybe? |
Création d'une nouvelle version de l'API (`/v2`) qui change l'entête HTTP `Accept` envoyée aux exporters des clients car la bibliothèque Go que nous utilisons afin de parser et enrichir les exporters de nos clients ne sait pas gérer le format OpenMetrics [1] qui peut être retournée par des exporters suivant la spécification. Les requêtes envoyées à nos clients contiennent désormais une entête HTTP leur indiquant la version de l'API interrogée. [1]: prometheus/client_golang#829 (comment) [2]: prometheus/common#214 JIRA: PAASCFY-2126
Create a new version of the API endpoint (`/v2`). This new version change the `Accept` HTTP header sent to the exporters requested (from `application/openmetrics-text` … to `text/plain`) because the Go library we use does not seems to support all OpenMetrics specificities ^1. The requests sent to the exporters contains a new HTTP header `X-Promfetcher-API-version` with the Promfetchers API version. ^1: Java actuator does respect the OpenMetrics specifications; the double quotes in the comments is not supported for example: > # HELP process_cpu_usage The \"recent cpu usage\" for the Java Virtual Machine process See also: [1]: prometheus/client_golang#829 (comment) [2]: prometheus/common#214
I received a bug report caddyserver/caddy#3940 which seems to be caused by 2 metrics exposed by the Go collector:
go_memstats_alloc_bytes
andgo_memstats_alloc_bytes_total
- in effect, these names seem to be ambiguous with respect to the OpenMetrics "magic"_total
suffix.This seems to be related to prometheus/common#253 (comment), though the conclusion in that issue seems to be "it's a bad idea, but won't break anything".
The metrics in question are defined here: https://github.com/prometheus/client_golang/blob/6007b2b5cae01203111de55f753e76d8dac1f529/prometheus/go_collector.go#L88..L104
I'm not super certain how to resolve this without removing or renaming one of the metrics, given that the python client seems to be behaving correctly with respect to the OpenMetrics spec (specifically https://github.com/OpenObservability/OpenMetrics/blob/master/specification/OpenMetrics.md#suffixes).
At the very least there seems to be an inconsistency between the Python and Go implementations...
LMK if there's anything I'm missing - on vacation so my brain isn't running in high-gear 😉
The text was updated successfully, but these errors were encountered: