Skip to content

Commit 995b5bd

Browse files
[r355] Distributor: Auto-deduce OTel translation strategy in OTLP endpoint if unset (#12371)
Backport e18b5d3 from #12369 Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com> Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
1 parent d48943f commit 995b5bd

6 files changed

Lines changed: 132 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* [CHANGE] Query-frontend: Remove experimental instant query splitting feature. #12267
1414
* [CHANGE] Distributor: Remove deprecated global HA tracker timeout configuration flags. #12321
1515
* [FEATURE] Distributor, ruler: Add experimental `-validation.name-validation-scheme` flag to specify the validation scheme for metric and label names. #12215
16-
* [FEATURE] Distributor: Add experimental `-distributor.otel-translation-strategy` flag to support configuring the metric and label name translation strategy in the OTLP endpoint. #12284 #12306
16+
* [FEATURE] Distributor: Add experimental `-distributor.otel-translation-strategy` flag to support configuring the metric and label name translation strategy in the OTLP endpoint. #12284 #12306 #12369
1717
* [ENHANCEMENT] Query-scheduler/query-frontend: Add native histogram definitions to `cortex_query_{scheduler|frontend}_queue_duration_seconds`. #12288
1818
* [ENHANCEMENT] Compactor: Add `-compactor.update-blocks-concurrency` flag to control concurrency for updating block metadata during bucket index updates, separate from deletion marker concurrency. #12117
1919
* [ENHANCEMENT] Stagger head compaction intervals across zones to prevent compactions from aligning simultaneously, which could otherwise cause strong consistency queries to fail when experimental ingest storage is enabled. #12090

pkg/distributor/otel_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,6 @@ func TestHandlerOTLPPush(t *testing.T) {
12601260
testLimits := &validation.Limits{
12611261
PromoteOTelResourceAttributes: tt.promoteResourceAttributes,
12621262
NameValidationScheme: validation.ValidationSchemeValue(model.LegacyValidation),
1263-
OTelTranslationStrategy: validation.OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithoutSuffixes),
12641263
OTelMetricSuffixesEnabled: false,
12651264
}
12661265
limits := validation.NewOverrides(

pkg/mimir/runtime_config_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/google/go-cmp/cmp/cmpopts"
1919
"github.com/grafana/dskit/flagext"
2020
"github.com/grafana/dskit/services"
21-
"github.com/prometheus/otlptranslator"
2221
"github.com/stretchr/testify/assert"
2322
"github.com/stretchr/testify/require"
2423

@@ -253,6 +252,5 @@ overrides:
253252
func getDefaultLimits() validation.Limits {
254253
limits := validation.Limits{}
255254
flagext.DefaultValues(&limits)
256-
limits.OTelTranslationStrategy = validation.OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithoutSuffixes)
257255
return limits
258256
}

pkg/util/validation/limits.go

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -616,21 +616,6 @@ func (l *Limits) Validate() error {
616616
return fmt.Errorf("OTLP translation strategy %s is not allowed unless metric suffixes are disabled", l.OTelTranslationStrategy)
617617
}
618618
case "":
619-
// Generate translation strategy based on other settings.
620-
switch validationScheme {
621-
case model.LegacyValidation:
622-
if l.OTelMetricSuffixesEnabled {
623-
l.OTelTranslationStrategy = OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithSuffixes)
624-
} else {
625-
l.OTelTranslationStrategy = OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithoutSuffixes)
626-
}
627-
case model.UTF8Validation:
628-
if l.OTelMetricSuffixesEnabled {
629-
l.OTelTranslationStrategy = OTelTranslationStrategyValue(otlptranslator.NoUTF8EscapingWithSuffixes)
630-
} else {
631-
l.OTelTranslationStrategy = OTelTranslationStrategyValue(otlptranslator.NoTranslation)
632-
}
633-
}
634619
default:
635620
return fmt.Errorf("unsupported OTLP translation strategy %q", l.OTelTranslationStrategy)
636621
}
@@ -1443,7 +1428,30 @@ func (o *Overrides) OTelNativeDeltaIngestion(tenantID string) bool {
14431428
}
14441429

14451430
func (o *Overrides) OTelTranslationStrategy(tenantID string) otlptranslator.TranslationStrategyOption {
1446-
return otlptranslator.TranslationStrategyOption(o.getOverridesForUser(tenantID).OTelTranslationStrategy)
1431+
strategy := otlptranslator.TranslationStrategyOption(o.getOverridesForUser(tenantID).OTelTranslationStrategy)
1432+
if strategy != "" {
1433+
return strategy
1434+
}
1435+
1436+
// Generate translation strategy based on other settings.
1437+
suffixesEnabled := o.OTelMetricSuffixesEnabled(tenantID)
1438+
switch scheme := o.NameValidationScheme(tenantID); scheme {
1439+
case model.LegacyValidation:
1440+
if suffixesEnabled {
1441+
strategy = otlptranslator.UnderscoreEscapingWithSuffixes
1442+
} else {
1443+
strategy = otlptranslator.UnderscoreEscapingWithoutSuffixes
1444+
}
1445+
case model.UTF8Validation:
1446+
if suffixesEnabled {
1447+
strategy = otlptranslator.NoUTF8EscapingWithSuffixes
1448+
} else {
1449+
strategy = otlptranslator.NoTranslation
1450+
}
1451+
default:
1452+
panic(fmt.Errorf("unrecognized name validation scheme: %s", scheme))
1453+
}
1454+
return strategy
14471455
}
14481456

14491457
// DistributorIngestionArtificialDelay returns the artificial ingestion latency for a given user.

pkg/util/validation/limits_mock.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package validation
77

88
import (
99
"github.com/grafana/dskit/flagext"
10-
"github.com/prometheus/otlptranslator"
1110
)
1211

1312
// mockTenantLimits exposes per-tenant limits based on a provided map
@@ -44,7 +43,6 @@ func MockOverrides(customize func(defaults *Limits, tenantLimits map[string]*Lim
4443
func MockDefaultLimits() *Limits {
4544
defaults := Limits{}
4645
flagext.DefaultValues(&defaults)
47-
defaults.OTelTranslationStrategy = OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithoutSuffixes)
4846
return &defaults
4947
}
5048

pkg/util/validation/limits_test.go

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,7 @@ func TestLimits_Validate(t *testing.T) {
16401640
}(),
16411641
verify: func(t *testing.T, cfg Limits) {
16421642
t.Helper()
1643-
assert.Equal(t, OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithoutSuffixes), cfg.OTelTranslationStrategy)
1643+
assert.Equal(t, OTelTranslationStrategyValue(""), cfg.OTelTranslationStrategy)
16441644
},
16451645
expectedErr: nil,
16461646
},
@@ -1655,7 +1655,7 @@ func TestLimits_Validate(t *testing.T) {
16551655
}(),
16561656
verify: func(t *testing.T, cfg Limits) {
16571657
t.Helper()
1658-
assert.Equal(t, OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithSuffixes), cfg.OTelTranslationStrategy)
1658+
assert.Equal(t, OTelTranslationStrategyValue(""), cfg.OTelTranslationStrategy)
16591659
},
16601660
expectedErr: nil,
16611661
},
@@ -1670,7 +1670,7 @@ func TestLimits_Validate(t *testing.T) {
16701670
}(),
16711671
verify: func(t *testing.T, cfg Limits) {
16721672
t.Helper()
1673-
assert.Equal(t, OTelTranslationStrategyValue(otlptranslator.NoUTF8EscapingWithSuffixes), cfg.OTelTranslationStrategy)
1673+
assert.Equal(t, OTelTranslationStrategyValue(""), cfg.OTelTranslationStrategy)
16741674
},
16751675
expectedErr: nil,
16761676
},
@@ -1685,7 +1685,7 @@ func TestLimits_Validate(t *testing.T) {
16851685
}(),
16861686
verify: func(t *testing.T, cfg Limits) {
16871687
t.Helper()
1688-
assert.Equal(t, OTelTranslationStrategyValue(otlptranslator.NoTranslation), cfg.OTelTranslationStrategy)
1688+
assert.Equal(t, OTelTranslationStrategyValue(""), cfg.OTelTranslationStrategy)
16891689
},
16901690
expectedErr: nil,
16911691
},
@@ -2166,6 +2166,109 @@ func TestLimitsCanonicalizeQueries(t *testing.T) {
21662166
}
21672167
}
21682168

2169+
func TestOverrides_OTelTranslationStrategy(t *testing.T) {
2170+
testCases := []struct {
2171+
name string
2172+
limits map[string]*Limits
2173+
tenantID string
2174+
expectedTranslationStrategy otlptranslator.TranslationStrategyOption
2175+
}{
2176+
{
2177+
name: "explicit strategy takes precedence",
2178+
limits: map[string]*Limits{
2179+
"tenant1": {
2180+
OTelTranslationStrategy: OTelTranslationStrategyValue(otlptranslator.UnderscoreEscapingWithSuffixes),
2181+
NameValidationScheme: ValidationSchemeValue(model.UTF8Validation),
2182+
OTelMetricSuffixesEnabled: false,
2183+
},
2184+
},
2185+
tenantID: "tenant1",
2186+
expectedTranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
2187+
},
2188+
{
2189+
name: "auto-deduced: legacy validation + suffixes enabled",
2190+
limits: map[string]*Limits{
2191+
"tenant1": {
2192+
OTelTranslationStrategy: OTelTranslationStrategyValue(""),
2193+
NameValidationScheme: ValidationSchemeValue(model.LegacyValidation),
2194+
OTelMetricSuffixesEnabled: true,
2195+
},
2196+
},
2197+
tenantID: "tenant1",
2198+
expectedTranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
2199+
},
2200+
{
2201+
name: "auto-deduced: legacy validation + suffixes disabled",
2202+
limits: map[string]*Limits{
2203+
"tenant1": {
2204+
OTelTranslationStrategy: OTelTranslationStrategyValue(""),
2205+
NameValidationScheme: ValidationSchemeValue(model.LegacyValidation),
2206+
OTelMetricSuffixesEnabled: false,
2207+
},
2208+
},
2209+
tenantID: "tenant1",
2210+
expectedTranslationStrategy: otlptranslator.UnderscoreEscapingWithoutSuffixes,
2211+
},
2212+
{
2213+
name: "auto-deduced: utf8 validation + suffixes enabled",
2214+
limits: map[string]*Limits{
2215+
"tenant1": {
2216+
OTelTranslationStrategy: OTelTranslationStrategyValue(""),
2217+
NameValidationScheme: ValidationSchemeValue(model.UTF8Validation),
2218+
OTelMetricSuffixesEnabled: true,
2219+
},
2220+
},
2221+
tenantID: "tenant1",
2222+
expectedTranslationStrategy: otlptranslator.NoUTF8EscapingWithSuffixes,
2223+
},
2224+
{
2225+
name: "auto-deduced: utf8 validation + suffixes disabled",
2226+
limits: map[string]*Limits{
2227+
"tenant1": {
2228+
OTelTranslationStrategy: OTelTranslationStrategyValue(""),
2229+
NameValidationScheme: ValidationSchemeValue(model.UTF8Validation),
2230+
OTelMetricSuffixesEnabled: false,
2231+
},
2232+
},
2233+
tenantID: "tenant1",
2234+
expectedTranslationStrategy: otlptranslator.NoTranslation,
2235+
},
2236+
{
2237+
name: "uses defaults for unknown tenant",
2238+
limits: map[string]*Limits{},
2239+
tenantID: "unknown",
2240+
expectedTranslationStrategy: otlptranslator.UnderscoreEscapingWithoutSuffixes, // Default: legacy + suffixes disabled
2241+
},
2242+
}
2243+
2244+
for _, tc := range testCases {
2245+
t.Run(tc.name, func(t *testing.T) {
2246+
defaults := getDefaultLimits()
2247+
overrides := NewOverrides(defaults, NewMockTenantLimits(tc.limits))
2248+
2249+
result := overrides.OTelTranslationStrategy(tc.tenantID)
2250+
assert.Equal(t, tc.expectedTranslationStrategy, result)
2251+
})
2252+
}
2253+
2254+
t.Run("panics on unknown name validation scheme", func(t *testing.T) {
2255+
limits := map[string]*Limits{
2256+
"tenant1": {
2257+
OTelTranslationStrategy: OTelTranslationStrategyValue(""),
2258+
NameValidationScheme: ValidationSchemeValue(999), // Invalid scheme
2259+
OTelMetricSuffixesEnabled: true,
2260+
},
2261+
}
2262+
2263+
defaults := getDefaultLimits()
2264+
overrides := NewOverrides(defaults, NewMockTenantLimits(limits))
2265+
2266+
assert.Panics(t, func() {
2267+
overrides.OTelTranslationStrategy("tenant1")
2268+
})
2269+
})
2270+
}
2271+
21692272
func getDefaultLimits() Limits {
21702273
limits := Limits{}
21712274
flagext.DefaultValues(&limits)

0 commit comments

Comments
 (0)