From 65df2d714754b6544faffde0d46ac37379c662a8 Mon Sep 17 00:00:00 2001 From: Arthur Silva Sens Date: Sun, 18 Feb 2024 15:29:40 -0300 Subject: [PATCH] Move OpenMetrics options to a separate struct Signed-off-by: Arthur Silva Sens --- examples/createdtimestamps/main.go | 6 ++- examples/exemplars/main.go | 4 +- examples/gocollector/main.go | 6 ++- examples/random/main.go | 6 ++- prometheus/promhttp/http.go | 69 +++++++++++++++++++----------- 5 files changed, 58 insertions(+), 33 deletions(-) diff --git a/examples/createdtimestamps/main.go b/examples/createdtimestamps/main.go index f83b959..296d0ac 100644 --- a/examples/createdtimestamps/main.go +++ b/examples/createdtimestamps/main.go @@ -51,8 +51,10 @@ func main() { "/metrics", promhttp.HandlerFor( registry, promhttp.HandlerOpts{ - EnableOpenMetrics: true, - EnableOpenMetricsCreatedMetrics: true, + OpenMetricsOptions: promhttp.OpenMetricsOptions{ + Enable: true, + EnableCreatedTimestamps: true, + }, }), ) // To test: curl -H 'Accept: application/openmetrics-text' localhost:8080/metrics diff --git a/examples/exemplars/main.go b/examples/exemplars/main.go index 798c2df..bdb0da2 100644 --- a/examples/exemplars/main.go +++ b/examples/exemplars/main.go @@ -61,7 +61,9 @@ func main() { "/metrics", promhttp.HandlerFor( registry, promhttp.HandlerOpts{ - EnableOpenMetrics: true, + OpenMetricsOptions: promhttp.OpenMetricsOptions{ + Enable: true, + }, }), ) // To test: curl -H 'Accept: application/openmetrics-text' localhost:8080/metrics diff --git a/examples/gocollector/main.go b/examples/gocollector/main.go index 9116314..2339d40 100644 --- a/examples/gocollector/main.go +++ b/examples/gocollector/main.go @@ -47,8 +47,10 @@ func main() { http.Handle("/metrics", promhttp.HandlerFor( reg, promhttp.HandlerOpts{ - // Opt into OpenMetrics to support exemplars. - EnableOpenMetrics: true, + OpenMetricsOptions: promhttp.OpenMetricsOptions{ + // Opt into OpenMetrics to support exemplars. + Enable: true, + }, }, )) fmt.Println("Hello world from new Go Collector!") diff --git a/examples/random/main.go b/examples/random/main.go index b4f6280..020dab1 100644 --- a/examples/random/main.go +++ b/examples/random/main.go @@ -134,8 +134,10 @@ func main() { http.Handle("/metrics", promhttp.HandlerFor( reg, promhttp.HandlerOpts{ - // Opt into OpenMetrics to support exemplars. - EnableOpenMetrics: true, + OpenMetricsOptions: promhttp.OpenMetricsOptions{ + // Opt into OpenMetrics to support exemplars. + Enable: true, + }, // Pass custom registry Registry: reg, }, diff --git a/prometheus/promhttp/http.go b/prometheus/promhttp/http.go index 1fd50ae..9872ecb 100644 --- a/prometheus/promhttp/http.go +++ b/prometheus/promhttp/http.go @@ -160,7 +160,7 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO } var contentType expfmt.Format - if opts.EnableOpenMetrics { + if opts.EnableOpenMetrics || opts.OpenMetricsOptions.Enable { contentType = expfmt.NegotiateIncludingOpenMetrics(req.Header) } else { contentType = expfmt.Negotiate(req.Header) @@ -181,7 +181,7 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO } var enc expfmt.Encoder - if opts.EnableOpenMetricsCreatedMetrics { + if opts.OpenMetricsOptions.EnableCreatedTimestamps { enc = expfmt.NewEncoder(w, contentType, expfmt.WithCreatedLines()) } else { enc = expfmt.NewEncoder(w, contentType) @@ -366,31 +366,11 @@ type HandlerOpts struct { // away). Until the implementation is improved, it is recommended to // implement a separate timeout in potentially slow Collectors. Timeout time.Duration - // If true, the experimental OpenMetrics encoding is added to the - // possible options during content negotiation. Note that Prometheus - // 2.5.0+ will negotiate OpenMetrics as first priority. OpenMetrics is - // the only way to transmit exemplars. However, the move to OpenMetrics - // is not completely transparent. Most notably, the values of "quantile" - // labels of Summaries and "le" labels of Histograms are formatted with - // a trailing ".0" if they would otherwise look like integer numbers - // (which changes the identity of the resulting series on the Prometheus - // server). + // Deprecated: Use OpenMetricsOptions.Enable instead. EnableOpenMetrics bool - // If 'EnableOpenMetrics' is true, 'EnableOpenMetricsCreatedMetrics' allows - // to add extra '_created' lines for counters, histograms and summaries, - // as defined in the OpenMetrics specification (see - // https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1). - // Created timestamps are used to improve the accuracy of reset detection, - // but be aware that it also increases the size of the payload. - // - // Prometheus introduced the feature flag 'created-timestamp-zero-ingestion' - // in version 2.50.0, but with support limited to the Prometheus protobuf - // format. Starting in Prometheus XXXX, the feature flag will be extended - // to the OpenMetrics text format. If using Prometheus XXXX or later, it - // is recommended to enable the feature flag in Prometheus, otherwise enabling - // _created lines will result in increased cardinality and no improvements - // in reset detection. - EnableOpenMetricsCreatedMetrics bool + // OpenMetricsOptions holds settings for the experimental OpenMetrics encoding. + // It can be used to enable OpenMetrics encoding and for setting extra options. + OpenMetricsOptions OpenMetricsOptions // ProcessStartTime allows setting process start timevalue that will be exposed // with "Process-Start-Time-Unix" response header along with the metrics // payload. This allow callers to have efficient transformations to cumulative @@ -401,6 +381,43 @@ type HandlerOpts struct { ProcessStartTime time.Time } +type OpenMetricsOptions struct { + // Enable specifies if the experimental OpenMetrics encoding is added to the + // possible options during content negotiation. + // + // Note that Prometheus 2.5.0+ might negotiate OpenMetrics Text format + // as first priority unless user uses custom scrape protocol prioritization or + // histograms feature is enabled (then Prometheus proto format is prioritized, + // which client_golang supports). + // + // Keep in mind that the move to OpenMetrics is not completely transparent. Most notably, + // the values of "quantile" labels of Summaries and "le" labels of Histograms are + // formatted with a trailing ".0" if they would otherwise look like integer numbers + // (which changes the identity of the resulting series on the Prometheus + // server). + // + // See other options in OpenMetricsOptions to learn how to enable some special + // features e.g. potentially dangerous created timestamp series. + Enable bool + // EnableCreatedTimestamps specifies if this handler should add, extra, synthetic + // Created Timestamps for counters, histograms and summaries, which for the current + // version of OpenMetrics are defined as extra series with the same name and "_created" + // suffix. See also the OpenMetrics specification for more details + // https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1 + // + // Created timestamps are used to improve the accuracy of reset detection, + // but the way it's designed in OpenMetrics 1.0 it also dramatically increases cardinality + // if the scraper does not handle those metrics correctly (converting to created timestamp + // instead of leaving those series as-is). New OpenMetrics versions might improve + // this situation. + // + // Prometheus introduced the feature flag 'created-timestamp-zero-ingestion' + // in version 2.50.0, but only for the Prometheus protobuf format. Starting in + // future Prometheus version, the feature flag will be extended to the OpenMetrics + // text format, thus safe to be enabled to improve accuracy of counters in Prometheus. + EnableCreatedTimestamps bool +} + // gzipAccepted returns whether the client will accept gzip-encoded content. func gzipAccepted(header http.Header) bool { a := header.Get(acceptEncodingHeader)