Skip to content

Commit

Permalink
OTLP receiver: Allow colons in non-standard units (#15728)
Browse files Browse the repository at this point in the history
Signed-off-by: Arve Knudsen <[email protected]>
  • Loading branch information
bboreham authored Dec 30, 2024
1 parent fefd8ec commit 7deebeb
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## unreleased

* [BUGFIX] OTLP receiver: Allow colons in non-standard units. #15710

## 3.1.0-rc.0 / 2024-12-18

* [SECURITY] upgrade golang.org/x/crypto to address reported CVE-2024-45337. #15691
Expand Down
8 changes: 4 additions & 4 deletions storage/remote/otlptranslator/prometheus/normalize_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"strings"
"unicode"

"github.com/prometheus/prometheus/util/strutil"
"go.opentelemetry.io/collector/pdata/pmetric"
)

Expand Down Expand Up @@ -120,18 +119,19 @@ func BuildCompliantName(metric pmetric.Metric, namespace string, addMetricSuffix
return metricName
}

var nonMetricNameCharRE = regexp.MustCompile(`[^a-zA-Z0-9:]`)

// Build a normalized name for the specified metric.
func normalizeName(metric pmetric.Metric, namespace string, allowUTF8 bool) string {
var nameTokens []string
var separators []string
if !allowUTF8 {
nonTokenMetricCharRE := regexp.MustCompile(`[^a-zA-Z0-9:]`)
// Split metric name into "tokens" (of supported metric name runes).
// Note that this has the side effect of replacing multiple consecutive underscores with a single underscore.
// This is part of the OTel to Prometheus specification: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.38.0/specification/compatibility/prometheus_and_openmetrics.md#otlp-metric-points-to-prometheus.
nameTokens = strings.FieldsFunc(
metric.Name(),
func(r rune) bool { return nonTokenMetricCharRE.MatchString(string(r)) },
func(r rune) bool { return nonMetricNameCharRE.MatchString(string(r)) },
)
} else {
translationFunc := func(r rune) bool { return !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != ':' }
Expand Down Expand Up @@ -289,7 +289,7 @@ func cleanUpUnit(unit string) string {
// This is part of the OTel to Prometheus specification: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.38.0/specification/compatibility/prometheus_and_openmetrics.md#otlp-metric-points-to-prometheus.
multipleUnderscoresRE := regexp.MustCompile(`__+`)
return strings.TrimPrefix(multipleUnderscoresRE.ReplaceAllString(
strutil.SanitizeLabelName(unit),
nonMetricNameCharRE.ReplaceAllString(unit, "_"),
"_",
), "_")
}
Expand Down
10 changes: 9 additions & 1 deletion storage/remote/otlptranslator/prometheus/normalize_name_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ func TestWhiteSpaces(t *testing.T) {

func TestNonStandardUnit(t *testing.T) {
require.Equal(t, "system_network_dropped", normalizeName(createGauge("system.network.dropped", "{packets}"), "", false))
// The normal metric name character set is allowed in non-standard units.
require.Equal(t, "system_network_dropped_nonstandard:_1", normalizeName(createGauge("system.network.dropped", "nonstandard:_1"), "", false))
}

func TestNonStandardUnitCounter(t *testing.T) {
Expand Down Expand Up @@ -70,6 +72,12 @@ func TestHertz(t *testing.T) {
func TestPer(t *testing.T) {
require.Equal(t, "broken_metric_speed_km_per_hour", normalizeName(createGauge("broken.metric.speed", "km/h"), "", false))
require.Equal(t, "astro_light_speed_limit_meters_per_second", normalizeName(createGauge("astro.light.speed_limit", "m/s"), "", false))
// The normal metric name character set is allowed in non-standard units.
require.Equal(t, "system_network_dropped_non_per_standard:_1", normalizeName(createGauge("system.network.dropped", "non/standard:_1"), "", false))

t.Run("invalid per unit", func(t *testing.T) {
require.Equal(t, "broken_metric_speed_km", normalizeName(createGauge("broken.metric.speed", "km/°"), "", false))
})
}

func TestPercent(t *testing.T) {
Expand All @@ -91,7 +99,7 @@ func TestAllowUTF8(t *testing.T) {
})
t.Run("disallow UTF8", func(t *testing.T) {
require.Equal(t, "unsupported_metric_temperature_F", normalizeName(createGauge("unsupported.metric.temperature", "°F"), "", false))
require.Equal(t, "unsupported_metric_weird", normalizeName(createGauge("unsupported.metric.weird", "+=.:,!* & #"), "", false))
require.Equal(t, "unsupported_metric_weird", normalizeName(createGauge("unsupported.metric.weird", "+=.,!* & #"), "", false))
require.Equal(t, "unsupported_metric_redundant_test_per_C", normalizeName(createGauge("unsupported.metric.redundant", "__test $/°C"), "", false))
require.Equal(t, "metric_with_foreign_characters", normalizeName(createGauge("metric_with_字符_foreign_characters", "ど"), "", false))
})
Expand Down

0 comments on commit 7deebeb

Please sign in to comment.