mirror of
https://github.com/prometheus/prometheus.git
synced 2025-11-09 21:01:19 +01:00
Add configuration parameters
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
parent
7cf4b5da55
commit
dd3a607d2d
@ -258,7 +258,9 @@ var (
|
||||
|
||||
// DefaultOTLPConfig is the default OTLP configuration.
|
||||
DefaultOTLPConfig = OTLPConfig{
|
||||
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||
LabelNameUnderscoreSanitization: true,
|
||||
LabelNamePreserveMultipleUnderscores: true,
|
||||
}
|
||||
)
|
||||
|
||||
@ -1609,6 +1611,14 @@ type OTLPConfig struct {
|
||||
// PromoteScopeMetadata controls whether to promote OTel scope metadata (i.e. name, version, schema URL, and attributes) to metric labels.
|
||||
// As per OTel spec, the aforementioned scope metadata should be identifying, i.e. made into metric labels.
|
||||
PromoteScopeMetadata bool `yaml:"promote_scope_metadata,omitempty"`
|
||||
// LabelNameUnderscoreSanitization controls whether to enable prepending of 'key_' to labels
|
||||
// starting with '_'. Reserved labels starting with `__` are not modified.
|
||||
// This is only relevant when AllowUTF8 is false (i.e., when using underscore escaping).
|
||||
LabelNameUnderscoreSanitization bool `yaml:"label_name_underscore_sanitization,omitempty"`
|
||||
// LabelNamePreserveMultipleUnderscores enables preserving of multiple consecutive underscores
|
||||
// in label names when AllowUTF8 is false. When false, multiple consecutive underscores are
|
||||
// collapsed to a single underscore during label name sanitization.
|
||||
LabelNamePreserveMultipleUnderscores bool `yaml:"label_name_preserve_multiple_underscores,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
|
||||
@ -175,7 +175,9 @@ var expectedConf = &Config{
|
||||
PromoteResourceAttributes: []string{
|
||||
"k8s.cluster.name", "k8s.job.name", "k8s.namespace.name",
|
||||
},
|
||||
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||
LabelNameUnderscoreSanitization: true,
|
||||
LabelNamePreserveMultipleUnderscores: true,
|
||||
},
|
||||
|
||||
RemoteReadConfigs: []*RemoteReadConfig{
|
||||
@ -1842,6 +1844,48 @@ func TestOTLPPromoteScopeMetadata(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestOTLPLabelUnderscoreSanitization(t *testing.T) {
|
||||
t.Run("defaults to true", func(t *testing.T) {
|
||||
conf, err := LoadFile(filepath.Join("testdata", "otlp_label_underscore_sanitization_defaults.good.yml"), false, promslog.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test that default values are true
|
||||
require.True(t, conf.OTLPConfig.LabelNameUnderscoreSanitization)
|
||||
require.True(t, conf.OTLPConfig.LabelNamePreserveMultipleUnderscores)
|
||||
})
|
||||
|
||||
t.Run("explicit enabled", func(t *testing.T) {
|
||||
conf, err := LoadFile(filepath.Join("testdata", "otlp_label_underscore_sanitization_enabled.good.yml"), false, promslog.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
out, err := yaml.Marshal(conf)
|
||||
require.NoError(t, err)
|
||||
var got Config
|
||||
require.NoError(t, yaml.UnmarshalStrict(out, &got))
|
||||
|
||||
require.True(t, got.OTLPConfig.LabelNameUnderscoreSanitization)
|
||||
require.True(t, got.OTLPConfig.LabelNamePreserveMultipleUnderscores)
|
||||
})
|
||||
|
||||
t.Run("explicit disabled", func(t *testing.T) {
|
||||
conf, err := LoadFile(filepath.Join("testdata", "otlp_label_underscore_sanitization_disabled.good.yml"), false, promslog.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
// When explicitly set to false, they should be false
|
||||
require.False(t, conf.OTLPConfig.LabelNameUnderscoreSanitization)
|
||||
require.False(t, conf.OTLPConfig.LabelNamePreserveMultipleUnderscores)
|
||||
})
|
||||
|
||||
t.Run("empty config uses defaults", func(t *testing.T) {
|
||||
conf, err := LoadFile(filepath.Join("testdata", "otlp_empty.yml"), false, promslog.NewNopLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Empty config should use default values (true)
|
||||
require.True(t, conf.OTLPConfig.LabelNameUnderscoreSanitization)
|
||||
require.True(t, conf.OTLPConfig.LabelNamePreserveMultipleUnderscores)
|
||||
})
|
||||
}
|
||||
|
||||
func TestOTLPAllowUTF8(t *testing.T) {
|
||||
t.Run("good config - NoUTF8EscapingWithSuffixes", func(t *testing.T) {
|
||||
fpath := filepath.Join("testdata", "otlp_allow_utf8.good.yml")
|
||||
|
||||
2
config/testdata/otlp_label_underscore_sanitization_defaults.good.yml
vendored
Normal file
2
config/testdata/otlp_label_underscore_sanitization_defaults.good.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
otlp:
|
||||
promote_resource_attributes: ["service.name"]
|
||||
3
config/testdata/otlp_label_underscore_sanitization_disabled.good.yml
vendored
Normal file
3
config/testdata/otlp_label_underscore_sanitization_disabled.good.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
otlp:
|
||||
label_name_underscore_sanitization: false
|
||||
label_name_preserve_multiple_underscores: false
|
||||
3
config/testdata/otlp_label_underscore_sanitization_enabled.good.yml
vendored
Normal file
3
config/testdata/otlp_label_underscore_sanitization_enabled.good.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
otlp:
|
||||
label_name_underscore_sanitization: true
|
||||
label_name_preserve_multiple_underscores: true
|
||||
@ -222,6 +222,15 @@ otlp:
|
||||
# Enables promotion of OTel scope metadata (i.e. name, version, schema URL, and attributes) to metric labels.
|
||||
# This is disabled by default for backwards compatibility, but according to OTel spec, scope metadata _should_ be identifying, i.e. translated to metric labels.
|
||||
[ promote_scope_metadata: <boolean> | default = false ]
|
||||
# Controls whether to enable prepending of 'key_' to labels starting with '_'.
|
||||
# Reserved labels starting with '__' are not modified.
|
||||
# This is only relevant when translation_strategy uses underscore escaping
|
||||
# (e.g., "UnderscoreEscapingWithSuffixes" or "UnderscoreEscapingWithoutSuffixes").
|
||||
[ label_name_underscore_sanitization: <boolean> | default = true ]
|
||||
# Enables preserving of multiple consecutive underscores in label names when
|
||||
# translation_strategy uses underscore escaping. When true (default), multiple
|
||||
# consecutive underscores are preserved during label name sanitization.
|
||||
[ label_name_preserve_multiple_underscores: <boolean> | default = true ]
|
||||
|
||||
# Settings related to the remote read feature.
|
||||
remote_read:
|
||||
|
||||
@ -90,7 +90,7 @@ func (c *PrometheusConverter) createAttributes(resource pcommon.Resource, attrib
|
||||
|
||||
labelNamer := otlptranslator.LabelNamer{
|
||||
UTF8Allowed: settings.AllowUTF8,
|
||||
UnderscoreLabelSanitization: settings.LabelNameUnderscoreLabelSanitization,
|
||||
UnderscoreLabelSanitization: settings.LabelNameUnderscoreSanitization,
|
||||
PreserveMultipleUnderscores: settings.LabelNamePreserveMultipleUnderscores,
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ func (c *PrometheusConverter) createAttributes(resource pcommon.Resource, attrib
|
||||
}
|
||||
}
|
||||
|
||||
err := settings.PromoteResourceAttributes.addPromotedAttributes(c.builder, resourceAttrs, settings.AllowUTF8)
|
||||
err := settings.PromoteResourceAttributes.addPromotedAttributes(c.builder, resourceAttrs, settings.AllowUTF8, settings.LabelNameUnderscoreSanitization, settings.LabelNamePreserveMultipleUnderscores)
|
||||
if err != nil {
|
||||
return labels.EmptyLabels(), err
|
||||
}
|
||||
|
||||
@ -67,15 +67,35 @@ func TestCreateAttributes(t *testing.T) {
|
||||
attrs.PutStr("metric-attr", "metric value")
|
||||
attrs.PutStr("metric-attr-other", "metric value other")
|
||||
|
||||
// Setup resources with underscores for sanitization tests
|
||||
resourceAttrsWithUnderscores := map[string]string{
|
||||
"service.name": "service name",
|
||||
"service.instance.id": "service ID",
|
||||
"_private": "private value",
|
||||
"__reserved__": "reserved value",
|
||||
"label___multi": "multi value",
|
||||
}
|
||||
resourceWithUnderscores := pcommon.NewResource()
|
||||
for k, v := range resourceAttrsWithUnderscores {
|
||||
resourceWithUnderscores.Attributes().PutStr(k, v)
|
||||
}
|
||||
attrsWithUnderscores := pcommon.NewMap()
|
||||
attrsWithUnderscores.PutStr("_metric_private", "private metric")
|
||||
attrsWithUnderscores.PutStr("metric___multi", "multi metric")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
scope scope
|
||||
promoteAllResourceAttributes bool
|
||||
promoteResourceAttributes []string
|
||||
promoteScope bool
|
||||
ignoreResourceAttributes []string
|
||||
ignoreAttrs []string
|
||||
expectedLabels labels.Labels
|
||||
name string
|
||||
resource pcommon.Resource
|
||||
attrs pcommon.Map
|
||||
scope scope
|
||||
promoteAllResourceAttributes bool
|
||||
promoteResourceAttributes []string
|
||||
promoteScope bool
|
||||
ignoreResourceAttributes []string
|
||||
ignoreAttrs []string
|
||||
labelNameUnderscoreLabelSanitization bool
|
||||
labelNamePreserveMultipleUnderscores bool
|
||||
expectedLabels labels.Labels
|
||||
}{
|
||||
{
|
||||
name: "Successful conversion without resource attribute promotion and without scope promotion",
|
||||
@ -251,6 +271,121 @@ func TestCreateAttributes(t *testing.T) {
|
||||
"otel_scope_attr2", "value2",
|
||||
),
|
||||
},
|
||||
// Label sanitization test cases
|
||||
{
|
||||
name: "Underscore sanitization enabled - prepends key_ to labels starting with single _",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"key_private", "private value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Underscore sanitization disabled - keeps labels with _ as-is",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"_private", "private value",
|
||||
"_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Multiple underscores preserved - keeps consecutive underscores",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"label___multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Multiple underscores collapsed - collapses to single underscore",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"label_multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Both sanitization options enabled",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private", "label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"key_private", "private value",
|
||||
"label___multi", "multi value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Both sanitization options disabled",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private", "label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"_private", "private value",
|
||||
"label_multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Reserved labels (starting with __) are never modified",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"__reserved__"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"__reserved__", "reserved value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@ -261,9 +396,24 @@ func TestCreateAttributes(t *testing.T) {
|
||||
PromoteResourceAttributes: tc.promoteResourceAttributes,
|
||||
IgnoreResourceAttributes: tc.ignoreResourceAttributes,
|
||||
}),
|
||||
PromoteScopeMetadata: tc.promoteScope,
|
||||
PromoteScopeMetadata: tc.promoteScope,
|
||||
LabelNameUnderscoreSanitization: tc.labelNameUnderscoreLabelSanitization,
|
||||
LabelNamePreserveMultipleUnderscores: tc.labelNamePreserveMultipleUnderscores,
|
||||
}
|
||||
lbls, err := c.createAttributes(resource, attrs, tc.scope, settings, tc.ignoreAttrs, false, Metadata{}, model.MetricNameLabel, "test_metric")
|
||||
// Use test case specific resource/attrs if provided, otherwise use defaults
|
||||
// Check if tc.resource is initialized (non-zero) by trying to get its attributes
|
||||
testResource := resource
|
||||
testAttrs := attrs
|
||||
// For pcommon types, we can check if they're non-zero by seeing if they have attributes
|
||||
// Since zero-initialized Resource is not valid, we use a simple heuristic:
|
||||
// if the struct has been explicitly set in the test case, use it
|
||||
if tc.resource != (pcommon.Resource{}) {
|
||||
testResource = tc.resource
|
||||
}
|
||||
if tc.attrs != (pcommon.Map{}) {
|
||||
testAttrs = tc.attrs
|
||||
}
|
||||
lbls, err := c.createAttributes(testResource, testAttrs, tc.scope, settings, tc.ignoreAttrs, false, Metadata{}, model.MetricNameLabel, "test_metric")
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.RequireEqual(t, lbls, tc.expectedLabels)
|
||||
|
||||
@ -54,9 +54,9 @@ type Settings struct {
|
||||
// PromoteScopeMetadata controls whether to promote OTel scope metadata to metric labels.
|
||||
PromoteScopeMetadata bool
|
||||
EnableTypeAndUnitLabels bool
|
||||
// LabelNameUnderscoreLabelSanitization controls whether to enable prepending of 'key' to labels
|
||||
// LabelNameUnderscoreSanitization controls whether to enable prepending of 'key' to labels
|
||||
// starting with '_'. Reserved labels starting with `__` are not modified.
|
||||
LabelNameUnderscoreLabelSanitization bool
|
||||
LabelNameUnderscoreSanitization bool
|
||||
// LabelNamePreserveMultipleUnderscores enables preserving of multiple
|
||||
// consecutive underscores in label names when AllowUTF8 is false.
|
||||
LabelNamePreserveMultipleUnderscores bool
|
||||
@ -310,12 +310,16 @@ func NewPromoteResourceAttributes(otlpCfg config.OTLPConfig) *PromoteResourceAtt
|
||||
}
|
||||
|
||||
// addPromotedAttributes adds labels for promoted resourceAttributes to the builder.
|
||||
func (s *PromoteResourceAttributes) addPromotedAttributes(builder *labels.Builder, resourceAttributes pcommon.Map, allowUTF8 bool) error {
|
||||
func (s *PromoteResourceAttributes) addPromotedAttributes(builder *labels.Builder, resourceAttributes pcommon.Map, allowUTF8, underscoreSanitization, preserveMultipleUnderscores bool) error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: allowUTF8}
|
||||
labelNamer := otlptranslator.LabelNamer{
|
||||
UTF8Allowed: allowUTF8,
|
||||
UnderscoreLabelSanitization: underscoreSanitization,
|
||||
PreserveMultipleUnderscores: preserveMultipleUnderscores,
|
||||
}
|
||||
if s.promoteAll {
|
||||
var err error
|
||||
resourceAttributes.Range(func(name string, value pcommon.Value) bool {
|
||||
|
||||
@ -649,15 +649,17 @@ func (rw *rwExporter) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) er
|
||||
combinedAppender := otlptranslator.NewCombinedAppender(app, rw.logger, rw.ingestCTZeroSample, rw.metrics)
|
||||
converter := otlptranslator.NewPrometheusConverter(combinedAppender)
|
||||
annots, err := converter.FromMetrics(ctx, md, otlptranslator.Settings{
|
||||
AddMetricSuffixes: otlpCfg.TranslationStrategy.ShouldAddSuffixes(),
|
||||
AllowUTF8: !otlpCfg.TranslationStrategy.ShouldEscape(),
|
||||
PromoteResourceAttributes: otlptranslator.NewPromoteResourceAttributes(otlpCfg),
|
||||
KeepIdentifyingResourceAttributes: otlpCfg.KeepIdentifyingResourceAttributes,
|
||||
ConvertHistogramsToNHCB: otlpCfg.ConvertHistogramsToNHCB,
|
||||
PromoteScopeMetadata: otlpCfg.PromoteScopeMetadata,
|
||||
AllowDeltaTemporality: rw.allowDeltaTemporality,
|
||||
LookbackDelta: rw.lookbackDelta,
|
||||
EnableTypeAndUnitLabels: rw.enableTypeAndUnitLabels,
|
||||
AddMetricSuffixes: otlpCfg.TranslationStrategy.ShouldAddSuffixes(),
|
||||
AllowUTF8: !otlpCfg.TranslationStrategy.ShouldEscape(),
|
||||
PromoteResourceAttributes: otlptranslator.NewPromoteResourceAttributes(otlpCfg),
|
||||
KeepIdentifyingResourceAttributes: otlpCfg.KeepIdentifyingResourceAttributes,
|
||||
ConvertHistogramsToNHCB: otlpCfg.ConvertHistogramsToNHCB,
|
||||
PromoteScopeMetadata: otlpCfg.PromoteScopeMetadata,
|
||||
AllowDeltaTemporality: rw.allowDeltaTemporality,
|
||||
LookbackDelta: rw.lookbackDelta,
|
||||
EnableTypeAndUnitLabels: rw.enableTypeAndUnitLabels,
|
||||
LabelNameUnderscoreSanitization: otlpCfg.LabelNameUnderscoreSanitization,
|
||||
LabelNamePreserveMultipleUnderscores: otlpCfg.LabelNamePreserveMultipleUnderscores,
|
||||
})
|
||||
|
||||
defer func() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user