From c6e6acc972c645d053c97ead24112b0b9918f41f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 00:17:39 +0000 Subject: [PATCH 1/2] fix(deps): update module github.com/prometheus/common to v0.62.0 --- exporters/prometheus/go.mod | 2 +- exporters/prometheus/go.sum | 4 ++-- internal/tools/go.mod | 2 +- internal/tools/go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/exporters/prometheus/go.mod b/exporters/prometheus/go.mod index 024f610a88e..c902f584cc8 100644 --- a/exporters/prometheus/go.mod +++ b/exporters/prometheus/go.mod @@ -5,7 +5,7 @@ go 1.22.0 require ( github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.61.0 + github.com/prometheus/common v0.62.0 github.com/stretchr/testify v1.10.0 go.opentelemetry.io/otel v1.34.0 go.opentelemetry.io/otel/metric v1.34.0 diff --git a/exporters/prometheus/go.sum b/exporters/prometheus/go.sum index c794f43a537..2d4a3fbbc01 100644 --- a/exporters/prometheus/go.sum +++ b/exporters/prometheus/go.sum @@ -29,8 +29,8 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= -github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= diff --git a/internal/tools/go.mod b/internal/tools/go.mod index 0fe9ddb13ba..118c04942f9 100644 --- a/internal/tools/go.mod +++ b/internal/tools/go.mod @@ -147,7 +147,7 @@ require ( github.com/polyfloyd/go-errorlint v1.7.0 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.61.0 // indirect + github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect diff --git a/internal/tools/go.sum b/internal/tools/go.sum index 280c1ffee64..193b432fcb6 100644 --- a/internal/tools/go.sum +++ b/internal/tools/go.sum @@ -347,8 +347,8 @@ github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+ github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ= -github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= From 2bff18eedea1a904d05fb879fa96cca4458d36ed Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Wed, 22 Jan 2025 17:41:16 +0000 Subject: [PATCH 2/2] fix prometheus tests --- CHANGELOG.md | 4 ++ exporters/prometheus/config_test.go | 2 +- exporters/prometheus/exporter.go | 70 ++++++++++++++++----------- exporters/prometheus/exporter_test.go | 10 ++-- 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7094c5248cb..78cd642217d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +### Changed + +- Update `github.com/prometheus/common` to v0.62.0., which changes the `NameValidationScheme` to `NoEscaping`. This allows metrics names to keep original delimiters (e.g. `.`), rather than replacing with underscores. This is controlled by the `Content-Type` header, or can be reverted by setting `NameValidationScheme` to `LegacyValidation` in `github.com/prometheus/common/model` (#6198) + ### Added - Add `ValueFromAttribute` and `KeyValueFromAttribute` in `go.opentelemetry.io/otel/log`. (#6180) diff --git a/exporters/prometheus/config_test.go b/exporters/prometheus/config_test.go index d0432cabada..26b0bfbdf10 100644 --- a/exporters/prometheus/config_test.go +++ b/exporters/prometheus/config_test.go @@ -133,7 +133,7 @@ func TestNewConfig(t *testing.T) { }, wantConfig: config{ registerer: prometheus.DefaultRegisterer, - namespace: "test_", + namespace: "test/_", }, }, } diff --git a/exporters/prometheus/exporter.go b/exporters/prometheus/exporter.go index 50c95a16f7f..a8677e93a26 100644 --- a/exporters/prometheus/exporter.go +++ b/exporters/prometheus/exporter.go @@ -96,7 +96,7 @@ type collector struct { // prometheus counters MUST have a _total suffix by default: // https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/compatibility/prometheus_and_openmetrics.md -const counterSuffix = "_total" +const counterSuffix = "total" // New returns a Prometheus Exporter. func New(opts ...Option) (*Exporter, error) { @@ -368,38 +368,38 @@ func createScopeInfoMetric(scope instrumentation.Scope) (prometheus.Metric, erro var unitSuffixes = map[string]string{ // Time - "d": "_days", - "h": "_hours", - "min": "_minutes", - "s": "_seconds", - "ms": "_milliseconds", - "us": "_microseconds", - "ns": "_nanoseconds", + "d": "days", + "h": "hours", + "min": "minutes", + "s": "seconds", + "ms": "milliseconds", + "us": "microseconds", + "ns": "nanoseconds", // Bytes - "By": "_bytes", - "KiBy": "_kibibytes", - "MiBy": "_mebibytes", - "GiBy": "_gibibytes", - "TiBy": "_tibibytes", - "KBy": "_kilobytes", - "MBy": "_megabytes", - "GBy": "_gigabytes", - "TBy": "_terabytes", + "By": "bytes", + "KiBy": "kibibytes", + "MiBy": "mebibytes", + "GiBy": "gibibytes", + "TiBy": "tibibytes", + "KBy": "kilobytes", + "MBy": "megabytes", + "GBy": "gigabytes", + "TBy": "terabytes", // SI - "m": "_meters", - "V": "_volts", - "A": "_amperes", - "J": "_joules", - "W": "_watts", - "g": "_grams", + "m": "meters", + "V": "volts", + "A": "amperes", + "J": "joules", + "W": "watts", + "g": "grams", // Misc - "Cel": "_celsius", - "Hz": "_hertz", - "1": "_ratio", - "%": "_percent", + "Cel": "celsius", + "Hz": "hertz", + "1": "ratio", + "%": "percent", } // getName returns the sanitized name, prefixed with the namespace and suffixed with unit. @@ -414,19 +414,31 @@ func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string { // Remove the _total suffix here, as we will re-add the total suffix // later, and it needs to come after the unit suffix. name = strings.TrimSuffix(name, counterSuffix) + // If the last character is an underscore, or would be converted to an underscore, trim it from the name. + // an underscore will be added back in later. + if convertsToUnderscore(rune(name[len(name)-1])) { + name = name[:len(name)-1] + } } if c.namespace != "" { name = c.namespace + name } if suffix, ok := unitSuffixes[m.Unit]; ok && !c.withoutUnits && !strings.HasSuffix(name, suffix) { - name += suffix + name += "_" + suffix } if addCounterSuffix { - name += counterSuffix + name += "_" + counterSuffix } return name } +// convertsToUnderscore returns true if the character would be converted to an +// underscore when the escaping scheme is underscore escaping. This is meant to +// capture any character that should be considered a "delimiter". +func convertsToUnderscore(b rune) bool { + return !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == ':' || (b >= '0' && b <= '9')) +} + func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType { switch v := m.Data.(type) { case metricdata.Histogram[int64], metricdata.Histogram[float64]: diff --git a/exporters/prometheus/exporter_test.go b/exporters/prometheus/exporter_test.go index 8718a217289..f40da6f7f31 100644 --- a/exporters/prometheus/exporter_test.go +++ b/exporters/prometheus/exporter_test.go @@ -35,7 +35,7 @@ func TestPrometheusExporter(t *testing.T) { recordMetrics func(ctx context.Context, meter otelmetric.Meter) options []Option expectedFile string - enableUTF8 bool + disableUTF8 bool }{ { name: "counter", @@ -195,6 +195,7 @@ func TestPrometheusExporter(t *testing.T) { { name: "sanitized attributes to labels", expectedFile: "testdata/sanitized_labels.txt", + disableUTF8: true, options: []Option{WithoutUnits()}, recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { opt := otelmetric.WithAttributes( @@ -404,7 +405,6 @@ func TestPrometheusExporter(t *testing.T) { { name: "counter utf-8", expectedFile: "testdata/counter_utf8.txt", - enableUTF8: true, recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { opt := otelmetric.WithAttributes( attribute.Key("A.G").String("B"), @@ -471,11 +471,11 @@ func TestPrometheusExporter(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - if tc.enableUTF8 { - model.NameValidationScheme = model.UTF8Validation + if tc.disableUTF8 { + model.NameValidationScheme = model.LegacyValidation defer func() { // Reset to defaults - model.NameValidationScheme = model.LegacyValidation + model.NameValidationScheme = model.UTF8Validation }() } ctx := context.Background()