diff --git a/config/config.go b/config/config.go index 12ca828ae8..7099ba325a 100644 --- a/config/config.go +++ b/config/config.go @@ -104,7 +104,7 @@ func Load(s string, logger *slog.Logger) (*Config, error) { } switch cfg.OTLPConfig.TranslationStrategy { - case UnderscoreEscapingWithSuffixes: + case UnderscoreEscapingWithSuffixes, UnderscoreEscapingWithoutSuffixes: case "": case NoTranslation, NoUTF8EscapingWithSuffixes: if cfg.GlobalConfig.MetricNameValidationScheme == model.LegacyValidation { @@ -1534,31 +1534,68 @@ func getGoGC() int { type translationStrategyOption string var ( - // NoUTF8EscapingWithSuffixes will accept metric/label names as they are. - // Unit and type suffixes may be added to metric names, according to certain rules. + // NoUTF8EscapingWithSuffixes will accept metric/label names as they are. Unit + // and type suffixes may be added to metric names, according to certain rules. NoUTF8EscapingWithSuffixes translationStrategyOption = "NoUTF8EscapingWithSuffixes" - // UnderscoreEscapingWithSuffixes is the default option for translating OTLP to Prometheus. - // This option will translate metric name characters that are not alphanumerics/underscores/colons to underscores, - // and label name characters that are not alphanumerics/underscores to underscores. - // Unit and type suffixes may be appended to metric names, according to certain rules. + // UnderscoreEscapingWithSuffixes is the default option for translating OTLP + // to Prometheus. This option will translate metric name characters that are + // not alphanumerics/underscores/colons to underscores, and label name + // characters that are not alphanumerics/underscores to underscores. Unit and + // type suffixes may be appended to metric names, according to certain rules. UnderscoreEscapingWithSuffixes translationStrategyOption = "UnderscoreEscapingWithSuffixes" + // UnderscoreEscapingWithoutSuffixes translates metric name characters that + // are not alphanumerics/underscores/colons to underscores, and label name + // characters that are not alphanumerics/underscores to underscores, but + // unlike UnderscoreEscapingWithSuffixes it does not append any suffixes to + // the names. + UnderscoreEscapingWithoutSuffixes translationStrategyOption = "UnderscoreEscapingWithoutSuffixes" // NoTranslation (EXPERIMENTAL): disables all translation of incoming metric - // and label names. This offers a way for the OTLP users to use native metric names, reducing confusion. + // and label names. This offers a way for the OTLP users to use native metric + // names, reducing confusion. // // WARNING: This setting has significant known risks and limitations (see - // https://prometheus.io/docs/practices/naming/ for details): - // * Impaired UX when using PromQL in plain YAML (e.g. alerts, rules, dashboard, autoscaling configuration). - // * Series collisions which in the best case may result in OOO errors, in the worst case a silently malformed - // time series. For instance, you may end up in situation of ingesting `foo.bar` series with unit - // `seconds` and a separate series `foo.bar` with unit `milliseconds`. + // https://prometheus.io/docs/practices/naming/ for details): * Impaired UX + // when using PromQL in plain YAML (e.g. alerts, rules, dashboard, autoscaling + // configuration). * Series collisions which in the best case may result in + // OOO errors, in the worst case a silently malformed time series. For + // instance, you may end up in situation of ingesting `foo.bar` series with + // unit `seconds` and a separate series `foo.bar` with unit `milliseconds`. // - // As a result, this setting is experimental and currently, should not be used in - // production systems. + // As a result, this setting is experimental and currently, should not be used + // in production systems. // - // TODO(ArthurSens): Mention `type-and-unit-labels` feature (https://github.com/prometheus/proposals/pull/39) once released, as potential mitigation of the above risks. + // TODO(ArthurSens): Mention `type-and-unit-labels` feature + // (https://github.com/prometheus/proposals/pull/39) once released, as + // potential mitigation of the above risks. NoTranslation translationStrategyOption = "NoTranslation" ) +// ShouldEscape returns true if the translation strategy requires that metric +// names be escaped. +func (o translationStrategyOption) ShouldEscape() bool { + switch o { + case UnderscoreEscapingWithSuffixes, UnderscoreEscapingWithoutSuffixes: + return true + case NoTranslation, NoUTF8EscapingWithSuffixes: + return false + default: + return false + } +} + +// ShouldAddSuffixes returns a bool deciding whether the given translation +// strategy should have suffixes added. +func (o translationStrategyOption) ShouldAddSuffixes() bool { + switch o { + case UnderscoreEscapingWithSuffixes, NoUTF8EscapingWithSuffixes: + return true + case UnderscoreEscapingWithoutSuffixes, NoTranslation: + return false + default: + return false + } +} + // OTLPConfig is the configuration for writing to the OTLP endpoint. type OTLPConfig struct { PromoteAllResourceAttributes bool `yaml:"promote_all_resource_attributes,omitempty"` diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index 580e57ed1a..8246de152e 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -197,6 +197,11 @@ otlp: # - "NoUTF8EscapingWithSuffixes" is a mode that relies on UTF-8 support in Prometheus. # It preserves all special characters like dots, but still adds required metric name suffixes # for units and _total, as UnderscoreEscapingWithSuffixes does. + # - "UnderscoreEscapingWithoutSuffixes" translates metric name characters that + # are not alphanumerics/underscores/colons to underscores, and label name + # characters that are not alphanumerics/underscores to underscores, but + # unlike UnderscoreEscapingWithSuffixes it does not append any suffixes to + # the names. # - (EXPERIMENTAL) "NoTranslation" is a mode that relies on UTF-8 support in Prometheus. # It preserves all special character like dots and won't append special suffixes for metric # unit and type. @@ -2286,7 +2291,7 @@ The following meta labels are available on targets during [relabeling](#relabel_ See below for the configuration options for STACKIT discovery: ```yaml -# The STACKIT project +# The STACKIT project project: # STACKIT region to use. No automatic discovery of the region is done. diff --git a/storage/remote/write_handler.go b/storage/remote/write_handler.go index 70c845f4aa..008ee03c36 100644 --- a/storage/remote/write_handler.go +++ b/storage/remote/write_handler.go @@ -594,9 +594,10 @@ func (rw *rwExporter) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) er otlpCfg := rw.config().OTLPConfig converter := otlptranslator.NewPrometheusConverter() + annots, err := converter.FromMetrics(ctx, md, otlptranslator.Settings{ - AddMetricSuffixes: otlpCfg.TranslationStrategy != config.NoTranslation, - AllowUTF8: otlpCfg.TranslationStrategy != config.UnderscoreEscapingWithSuffixes, + AddMetricSuffixes: otlpCfg.TranslationStrategy.ShouldAddSuffixes(), + AllowUTF8: !otlpCfg.TranslationStrategy.ShouldEscape(), PromoteResourceAttributes: otlptranslator.NewPromoteResourceAttributes(otlpCfg), KeepIdentifyingResourceAttributes: otlpCfg.KeepIdentifyingResourceAttributes, ConvertHistogramsToNHCB: otlpCfg.ConvertHistogramsToNHCB, diff --git a/storage/remote/write_test.go b/storage/remote/write_test.go index 45f2b075ee..6121bb114f 100644 --- a/storage/remote/write_test.go +++ b/storage/remote/write_test.go @@ -440,7 +440,32 @@ func TestOTLPWriteHandler(t *testing.T) { }, }, }, - + { + name: "UnderscoreEscapingWithoutSuffixes", + otlpCfg: config.OTLPConfig{ + TranslationStrategy: config.UnderscoreEscapingWithoutSuffixes, + }, + expectedSamples: []mockSample{ + { + l: labels.New(labels.Label{Name: "__name__", Value: "test_counter"}, + labels.Label{Name: "foo_bar", Value: "baz"}, + labels.Label{Name: "instance", Value: "test-instance"}, + labels.Label{Name: "job", Value: "test-service"}), + t: timestamp.UnixMilli(), + v: 10.0, + }, + { + l: labels.New( + labels.Label{Name: "__name__", Value: "target_info"}, + labels.Label{Name: "host_name", Value: "test-host"}, + labels.Label{Name: "instance", Value: "test-instance"}, + labels.Label{Name: "job", Value: "test-service"}, + ), + t: timestamp.UnixMilli(), + v: 1, + }, + }, + }, { name: "NoUTF8EscapingWithSuffixes", otlpCfg: config.OTLPConfig{