diff --git a/Documentation/api.md b/Documentation/api.md index 9e1e37a6c..6a76ace1d 100644 --- a/Documentation/api.md +++ b/Documentation/api.md @@ -2704,6 +2704,20 @@ If Prometheus version is >= 2.45.0 and the <code>enforcedBodySizeLimit</code> </tr> <tr> <td> +<code>nameValidationScheme</code><br/> +<em> +<a href="#monitoring.coreos.com/v1.NameValidationSchemeOptions"> +NameValidationSchemeOptions +</a> +</em> +</td> +<td> +<em>(Optional)</em> +<p>Specifies the validation scheme for metric and label names.</p> +</td> +</tr> +<tr> +<td> <code>minReadySeconds</code><br/> <em> uint32 @@ -7695,6 +7709,20 @@ If Prometheus version is >= 2.45.0 and the <code>enforcedBodySizeLimit</code> </tr> <tr> <td> +<code>nameValidationScheme</code><br/> +<em> +<a href="#monitoring.coreos.com/v1.NameValidationSchemeOptions"> +NameValidationSchemeOptions +</a> +</em> +</td> +<td> +<em>(Optional)</em> +<p>Specifies the validation scheme for metric and label names.</p> +</td> +</tr> +<tr> +<td> <code>minReadySeconds</code><br/> <em> uint32 @@ -9540,6 +9568,31 @@ Duration </tr> </tbody> </table> +<h3 id="monitoring.coreos.com/v1.NameValidationSchemeOptions">NameValidationSchemeOptions +(<code>string</code> alias)</h3> +<p> +(<em>Appears on:</em><a href="#monitoring.coreos.com/v1.CommonPrometheusFields">CommonPrometheusFields</a>) +</p> +<div> +<p>Specifies the validation scheme for metric and label names. +Supported values are: +* <code>UTF8NameValidationScheme</code> for UTF-8 support. +* <code>LegacyNameValidationScheme</code> for letters, numbers, colons, and underscores.</p> +<p>Note that <code>LegacyNameValidationScheme</code> cannot be used along with the OpenTelemetry <code>NoUTF8EscapingWithSuffixes</code> translation strategy (if enabled).</p> +</div> +<table> +<thead> +<tr> +<th>Value</th> +<th>Description</th> +</tr> +</thead> +<tbody><tr><td><p>"Legacy"</p></td> +<td></td> +</tr><tr><td><p>"UTF8"</p></td> +<td></td> +</tr></tbody> +</table> <h3 id="monitoring.coreos.com/v1.NamespaceSelector">NamespaceSelector </h3> <p> @@ -12433,6 +12486,20 @@ If Prometheus version is >= 2.45.0 and the <code>enforcedBodySizeLimit</code> </tr> <tr> <td> +<code>nameValidationScheme</code><br/> +<em> +<a href="#monitoring.coreos.com/v1.NameValidationSchemeOptions"> +NameValidationSchemeOptions +</a> +</em> +</td> +<td> +<em>(Optional)</em> +<p>Specifies the validation scheme for metric and label names.</p> +</td> +</tr> +<tr> +<td> <code>minReadySeconds</code><br/> <em> uint32 @@ -19082,6 +19149,20 @@ If Prometheus version is >= 2.45.0 and the <code>enforcedBodySizeLimit</code> </tr> <tr> <td> +<code>nameValidationScheme</code><br/> +<em> +<a href="#monitoring.coreos.com/v1.NameValidationSchemeOptions"> +NameValidationSchemeOptions +</a> +</em> +</td> +<td> +<em>(Optional)</em> +<p>Specifies the validation scheme for metric and label names.</p> +</td> +</tr> +<tr> +<td> <code>minReadySeconds</code><br/> <em> uint32 @@ -26953,6 +27034,20 @@ If Prometheus version is >= 2.45.0 and the <code>enforcedBodySizeLimit</code> </tr> <tr> <td> +<code>nameValidationScheme</code><br/> +<em> +<a href="#monitoring.coreos.com/v1.NameValidationSchemeOptions"> +NameValidationSchemeOptions +</a> +</em> +</td> +<td> +<em>(Optional)</em> +<p>Specifies the validation scheme for metric and label names.</p> +</td> +</tr> +<tr> +<td> <code>minReadySeconds</code><br/> <em> uint32 diff --git a/bundle.yaml b/bundle.yaml index da58110bf..fee45e15e 100644 --- a/bundle.yaml +++ b/bundle.yaml @@ -25669,6 +25669,13 @@ spec: - StatefulSet - DaemonSet type: string + nameValidationScheme: + description: Specifies the validation scheme for metric and label + names. + enum: + - UTF8 + - Legacy + type: string nodeSelector: additionalProperties: type: string @@ -37019,6 +37026,13 @@ spec: enabling the StatefulSetMinReadySeconds feature gate. format: int32 type: integer + nameValidationScheme: + description: Specifies the validation scheme for metric and label + names. + enum: + - UTF8 + - Legacy + type: string nodeSelector: additionalProperties: type: string diff --git a/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheusagents.yaml b/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheusagents.yaml index 48264c48d..be9616887 100644 --- a/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheusagents.yaml +++ b/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheusagents.yaml @@ -4726,6 +4726,13 @@ spec: - StatefulSet - DaemonSet type: string + nameValidationScheme: + description: Specifies the validation scheme for metric and label + names. + enum: + - UTF8 + - Legacy + type: string nodeSelector: additionalProperties: type: string diff --git a/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheuses.yaml b/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheuses.yaml index 8416a7e88..52daccb57 100644 --- a/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheuses.yaml +++ b/example/prometheus-operator-crd-full/monitoring.coreos.com_prometheuses.yaml @@ -5435,6 +5435,13 @@ spec: enabling the StatefulSetMinReadySeconds feature gate. format: int32 type: integer + nameValidationScheme: + description: Specifies the validation scheme for metric and label + names. + enum: + - UTF8 + - Legacy + type: string nodeSelector: additionalProperties: type: string diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml index c1f948378..438555baf 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_prometheusagents.yaml @@ -4727,6 +4727,13 @@ spec: - StatefulSet - DaemonSet type: string + nameValidationScheme: + description: Specifies the validation scheme for metric and label + names. + enum: + - UTF8 + - Legacy + type: string nodeSelector: additionalProperties: type: string diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml index baaec307d..a17603cb1 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml @@ -5436,6 +5436,13 @@ spec: enabling the StatefulSetMinReadySeconds feature gate. format: int32 type: integer + nameValidationScheme: + description: Specifies the validation scheme for metric and label + names. + enum: + - UTF8 + - Legacy + type: string nodeSelector: additionalProperties: type: string diff --git a/jsonnet/prometheus-operator/prometheusagents-crd.json b/jsonnet/prometheus-operator/prometheusagents-crd.json index a44b26add..bde1b3b2c 100644 --- a/jsonnet/prometheus-operator/prometheusagents-crd.json +++ b/jsonnet/prometheus-operator/prometheusagents-crd.json @@ -4023,6 +4023,14 @@ ], "type": "string" }, + "nameValidationScheme": { + "description": "Specifies the validation scheme for metric and label names.", + "enum": [ + "UTF8", + "Legacy" + ], + "type": "string" + }, "nodeSelector": { "additionalProperties": { "type": "string" diff --git a/jsonnet/prometheus-operator/prometheuses-crd.json b/jsonnet/prometheus-operator/prometheuses-crd.json index 2aa5056f4..2a75a0b3f 100644 --- a/jsonnet/prometheus-operator/prometheuses-crd.json +++ b/jsonnet/prometheus-operator/prometheuses-crd.json @@ -4624,6 +4624,14 @@ "format": "int32", "type": "integer" }, + "nameValidationScheme": { + "description": "Specifies the validation scheme for metric and label names.", + "enum": [ + "UTF8", + "Legacy" + ], + "type": "string" + }, "nodeSelector": { "additionalProperties": { "type": "string" diff --git a/pkg/apis/monitoring/v1/prometheus_types.go b/pkg/apis/monitoring/v1/prometheus_types.go index 1e31c56cc..29f178c2e 100644 --- a/pkg/apis/monitoring/v1/prometheus_types.go +++ b/pkg/apis/monitoring/v1/prometheus_types.go @@ -674,6 +674,10 @@ type CommonPrometheusFields struct { // EnforcedBodySizeLimit ByteSize `json:"enforcedBodySizeLimit,omitempty"` + // Specifies the validation scheme for metric and label names. + // +optional + NameValidationScheme *NameValidationSchemeOptions `json:"nameValidationScheme,omitempty"` + // Minimum number of seconds for which a newly created Pod should be ready // without any of its container crashing for it to be considered available. // Defaults to 0 (pod will be considered available as soon as it is ready) @@ -846,6 +850,20 @@ type CommonPrometheusFields struct { Runtime *RuntimeConfig `json:"runtime,omitempty"` } +// Specifies the validation scheme for metric and label names. +// Supported values are: +// * `UTF8NameValidationScheme` for UTF-8 support. +// * `LegacyNameValidationScheme` for letters, numbers, colons, and underscores. +// +// Note that `LegacyNameValidationScheme` cannot be used along with the OpenTelemetry `NoUTF8EscapingWithSuffixes` translation strategy (if enabled). +// +kubebuilder:validation:Enum=UTF8;Legacy +type NameValidationSchemeOptions string + +const ( + UTF8NameValidationScheme NameValidationSchemeOptions = "UTF8" + LegacyNameValidationScheme NameValidationSchemeOptions = "Legacy" +) + // +kubebuilder:validation:Enum=HTTP;ProcessSignal type ReloadStrategyType string diff --git a/pkg/apis/monitoring/v1/zz_generated.deepcopy.go b/pkg/apis/monitoring/v1/zz_generated.deepcopy.go index 41c305c19..f4f430f81 100644 --- a/pkg/apis/monitoring/v1/zz_generated.deepcopy.go +++ b/pkg/apis/monitoring/v1/zz_generated.deepcopy.go @@ -920,6 +920,11 @@ func (in *CommonPrometheusFields) DeepCopyInto(out *CommonPrometheusFields) { *out = new(uint64) **out = **in } + if in.NameValidationScheme != nil { + in, out := &in.NameValidationScheme, &out.NameValidationScheme + *out = new(NameValidationSchemeOptions) + **out = **in + } if in.MinReadySeconds != nil { in, out := &in.MinReadySeconds, &out.MinReadySeconds *out = new(uint32) diff --git a/pkg/client/applyconfiguration/monitoring/v1/commonprometheusfields.go b/pkg/client/applyconfiguration/monitoring/v1/commonprometheusfields.go index 774e01270..8fdd50bd6 100644 --- a/pkg/client/applyconfiguration/monitoring/v1/commonprometheusfields.go +++ b/pkg/client/applyconfiguration/monitoring/v1/commonprometheusfields.go @@ -94,6 +94,7 @@ type CommonPrometheusFieldsApplyConfiguration struct { EnforcedLabelValueLengthLimit *uint64 `json:"enforcedLabelValueLengthLimit,omitempty"` EnforcedKeepDroppedTargets *uint64 `json:"enforcedKeepDroppedTargets,omitempty"` EnforcedBodySizeLimit *monitoringv1.ByteSize `json:"enforcedBodySizeLimit,omitempty"` + NameValidationScheme *monitoringv1.NameValidationSchemeOptions `json:"nameValidationScheme,omitempty"` MinReadySeconds *uint32 `json:"minReadySeconds,omitempty"` HostAliases []HostAliasApplyConfiguration `json:"hostAliases,omitempty"` AdditionalArgs []ArgumentApplyConfiguration `json:"additionalArgs,omitempty"` @@ -711,6 +712,14 @@ func (b *CommonPrometheusFieldsApplyConfiguration) WithEnforcedBodySizeLimit(val return b } +// WithNameValidationScheme sets the NameValidationScheme field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NameValidationScheme field is set to the value of the last call. +func (b *CommonPrometheusFieldsApplyConfiguration) WithNameValidationScheme(value monitoringv1.NameValidationSchemeOptions) *CommonPrometheusFieldsApplyConfiguration { + b.NameValidationScheme = &value + return b +} + // WithMinReadySeconds sets the MinReadySeconds field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the MinReadySeconds field is set to the value of the last call. diff --git a/pkg/client/applyconfiguration/monitoring/v1/prometheusspec.go b/pkg/client/applyconfiguration/monitoring/v1/prometheusspec.go index b0d8385ef..77708e1ab 100644 --- a/pkg/client/applyconfiguration/monitoring/v1/prometheusspec.go +++ b/pkg/client/applyconfiguration/monitoring/v1/prometheusspec.go @@ -645,6 +645,14 @@ func (b *PrometheusSpecApplyConfiguration) WithEnforcedBodySizeLimit(value monit return b } +// WithNameValidationScheme sets the NameValidationScheme field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NameValidationScheme field is set to the value of the last call. +func (b *PrometheusSpecApplyConfiguration) WithNameValidationScheme(value monitoringv1.NameValidationSchemeOptions) *PrometheusSpecApplyConfiguration { + b.NameValidationScheme = &value + return b +} + // WithMinReadySeconds sets the MinReadySeconds field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the MinReadySeconds field is set to the value of the last call. diff --git a/pkg/client/applyconfiguration/monitoring/v1alpha1/prometheusagentspec.go b/pkg/client/applyconfiguration/monitoring/v1alpha1/prometheusagentspec.go index 8b46a1fe0..3ee632630 100644 --- a/pkg/client/applyconfiguration/monitoring/v1alpha1/prometheusagentspec.go +++ b/pkg/client/applyconfiguration/monitoring/v1alpha1/prometheusagentspec.go @@ -633,6 +633,14 @@ func (b *PrometheusAgentSpecApplyConfiguration) WithEnforcedBodySizeLimit(value return b } +// WithNameValidationScheme sets the NameValidationScheme field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NameValidationScheme field is set to the value of the last call. +func (b *PrometheusAgentSpecApplyConfiguration) WithNameValidationScheme(value monitoringv1.NameValidationSchemeOptions) *PrometheusAgentSpecApplyConfiguration { + b.NameValidationScheme = &value + return b +} + // WithMinReadySeconds sets the MinReadySeconds field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the MinReadySeconds field is set to the value of the last call. diff --git a/pkg/prometheus/promcfg.go b/pkg/prometheus/promcfg.go index 38659bcef..fb490d780 100644 --- a/pkg/prometheus/promcfg.go +++ b/pkg/prometheus/promcfg.go @@ -4497,6 +4497,8 @@ func (cg *ConfigGenerator) generateScrapeConfig( func (cg *ConfigGenerator) appendOTLPConfig(cfg yaml.MapSlice) (yaml.MapSlice, error) { otlpConfig := cg.prom.GetCommonPrometheusFields().OTLP + nameValidationScheme := cg.prom.GetCommonPrometheusFields().NameValidationScheme + if otlpConfig == nil { return cfg, nil } @@ -4505,6 +4507,10 @@ func (cg *ConfigGenerator) appendOTLPConfig(cfg yaml.MapSlice) (yaml.MapSlice, e return cfg, fmt.Errorf("OTLP configuration is only supported from Prometheus version 2.55.0") } + if ptr.Deref(otlpConfig.TranslationStrategy, "") == monitoringv1.NoUTF8EscapingWithSuffixes && ptr.Deref(nameValidationScheme, "") == monitoringv1.LegacyNameValidationScheme { + return cfg, fmt.Errorf("nameValidationScheme %q is not compatible with OTLP translation strategy %q", monitoringv1.LegacyNameValidationScheme, monitoringv1.NoUTF8EscapingWithSuffixes) + } + otlp := yaml.MapSlice{} if len(otlpConfig.PromoteResourceAttributes) > 0 { @@ -4664,11 +4670,15 @@ func (cg *ConfigGenerator) addFiltersToYaml(cfg yaml.MapSlice, filters []monitor } func (cg *ConfigGenerator) buildGlobalConfig() yaml.MapSlice { + cpf := cg.prom.GetCommonPrometheusFields() cfg := yaml.MapSlice{} cfg = cg.appendScrapeIntervals(cfg) cfg = cg.addScrapeProtocols(cfg, cg.prom.GetCommonPrometheusFields().ScrapeProtocols) cfg = cg.appendExternalLabels(cfg) cfg = cg.appendScrapeLimits(cfg) + if cpf.NameValidationScheme != nil { + cg.WithMinimumVersion("3.0.0").AppendMapItem(cfg, "metric_name_validation_scheme", *cpf.NameValidationScheme) + } return cfg } diff --git a/pkg/prometheus/promcfg_test.go b/pkg/prometheus/promcfg_test.go index 11c3989a1..0a1663a8c 100644 --- a/pkg/prometheus/promcfg_test.go +++ b/pkg/prometheus/promcfg_test.go @@ -8582,13 +8582,76 @@ func TestScrapeConfigSpecConfigWithHetznerSD(t *testing.T) { } } +func TestAppendNameValidationScheme(t *testing.T) { + testCases := []struct { + name string + version string + nameValidationScheme *monitoringv1.NameValidationSchemeOptions + expectedCfg string + }{ + { + name: "UTF8 nameValidationScheme withPrometheus Version 3", + version: "v3.0.0-beta.0", + nameValidationScheme: ptr.To(monitoringv1.UTF8NameValidationScheme), + expectedCfg: "NameValidationSchemeUTF8WithPrometheusV3.golden", + }, + { + name: "Legacy nameValidationScheme with Prometheus Version 3", + version: "v3.0.0-beta.0", + nameValidationScheme: ptr.To(monitoringv1.LegacyNameValidationScheme), + expectedCfg: "NameValidationSchemeLegacyWithPrometheusV3.golden", + }, + { + name: "Legacy nameValidationScheme with Prometheus Version 3", + version: "v2.55.0", + nameValidationScheme: ptr.To(monitoringv1.LegacyNameValidationScheme), + expectedCfg: "NameValidationSchemeLegacyWithPrometheusLowerThanV3.golden", + }, + { + name: "Legacy nameValidationScheme with Prometheus Version 3", + version: "v2.55.0", + nameValidationScheme: ptr.To(monitoringv1.LegacyNameValidationScheme), + expectedCfg: "NameValidationSchemeLegacyWithPrometheusLowerThanV3.golden", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + p := defaultPrometheus() + if tc.version != "" { + p.Spec.CommonPrometheusFields.Version = tc.version + } + if tc.nameValidationScheme != nil { + p.Spec.CommonPrometheusFields.NameValidationScheme = tc.nameValidationScheme + } + + cg := mustNewConfigGenerator(t, p) + cfg, err := cg.GenerateServerConfiguration( + p, + nil, + nil, + nil, + nil, + &assets.StoreBuilder{}, + nil, + nil, + nil, + nil, + ) + require.NoError(t, err) + + golden.Assert(t, string(cfg), tc.expectedCfg) + }) + } +} func TestOTLPConfig(t *testing.T) { testCases := []struct { - otlpConfig *monitoringv1.OTLPConfig - name string - version string - expectedErr bool - golden string + otlpConfig *monitoringv1.OTLPConfig + nameValScheme *monitoringv1.NameValidationSchemeOptions + name string + version string + expectedErr bool + golden string }{ { name: "Config promote resource attributes", @@ -8638,6 +8701,24 @@ func TestOTLPConfig(t *testing.T) { }, golden: "OTLPConfig_Config_translation_strategy_with_unsupported_version.golden", }, + { + name: "Config Legacy nameValidationScheme with OTLP translation strategy NoUTF8", + version: "v3.0.0", + otlpConfig: &monitoringv1.OTLPConfig{ + TranslationStrategy: ptr.To(monitoringv1.NoUTF8EscapingWithSuffixes), + }, + nameValScheme: ptr.To(monitoringv1.LegacyNameValidationScheme), + expectedErr: true, + }, + { + name: "Config Legacy nameValidationScheme with OTLP translation strategy UnderscoreEscapingWithSuffixes", + version: "v3.0.0", + otlpConfig: &monitoringv1.OTLPConfig{ + TranslationStrategy: ptr.To(monitoringv1.UnderscoreEscapingWithSuffixes), + }, + nameValScheme: ptr.To(monitoringv1.LegacyNameValidationScheme), + golden: "OTLPConfig_Config_translation_strategy_with_suffixes_and_name_validation_scheme.golden", + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -8650,6 +8731,8 @@ func TestOTLPConfig(t *testing.T) { p.Spec.CommonPrometheusFields.OTLP = tc.otlpConfig + p.Spec.CommonPrometheusFields.NameValidationScheme = tc.nameValScheme + cg := mustNewConfigGenerator(t, p) cfg, err := cg.GenerateServerConfiguration( diff --git a/pkg/prometheus/testdata/NameValidationSchemeLegacyWithPrometheusLowerThanV3.golden b/pkg/prometheus/testdata/NameValidationSchemeLegacyWithPrometheusLowerThanV3.golden new file mode 100644 index 000000000..609303fe8 --- /dev/null +++ b/pkg/prometheus/testdata/NameValidationSchemeLegacyWithPrometheusLowerThanV3.golden @@ -0,0 +1,7 @@ +global: + scrape_interval: 30s + external_labels: + prometheus: default/test + prometheus_replica: $(POD_NAME) + evaluation_interval: 30s +scrape_configs: [] diff --git a/pkg/prometheus/testdata/NameValidationSchemeLegacyWithPrometheusV3.golden b/pkg/prometheus/testdata/NameValidationSchemeLegacyWithPrometheusV3.golden new file mode 100644 index 000000000..609303fe8 --- /dev/null +++ b/pkg/prometheus/testdata/NameValidationSchemeLegacyWithPrometheusV3.golden @@ -0,0 +1,7 @@ +global: + scrape_interval: 30s + external_labels: + prometheus: default/test + prometheus_replica: $(POD_NAME) + evaluation_interval: 30s +scrape_configs: [] diff --git a/pkg/prometheus/testdata/NameValidationSchemeUTF8WithPrometheusV3.golden b/pkg/prometheus/testdata/NameValidationSchemeUTF8WithPrometheusV3.golden new file mode 100644 index 000000000..609303fe8 --- /dev/null +++ b/pkg/prometheus/testdata/NameValidationSchemeUTF8WithPrometheusV3.golden @@ -0,0 +1,7 @@ +global: + scrape_interval: 30s + external_labels: + prometheus: default/test + prometheus_replica: $(POD_NAME) + evaluation_interval: 30s +scrape_configs: [] diff --git a/pkg/prometheus/testdata/OTLPConfig_Config_translation_strategy_with_suffixes_and_name_validation_scheme.golden b/pkg/prometheus/testdata/OTLPConfig_Config_translation_strategy_with_suffixes_and_name_validation_scheme.golden new file mode 100644 index 000000000..0088555f1 --- /dev/null +++ b/pkg/prometheus/testdata/OTLPConfig_Config_translation_strategy_with_suffixes_and_name_validation_scheme.golden @@ -0,0 +1,9 @@ +global: + scrape_interval: 30s + external_labels: + prometheus: default/test + prometheus_replica: $(POD_NAME) + evaluation_interval: 30s +scrape_configs: [] +otlp: + translation_strategy: UnderscoreEscapingWithSuffixes