From e1631f8a6cea974f35bb32c5f6a5dd7f63158251 Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Thu, 13 Jul 2023 15:42:50 +0000 Subject: [PATCH] prometheusreceiver: add trim_metric_suffixes configuration option --- ...metheus-receiver-normalization-config.yaml | 23 +++++++++++ pkg/translator/prometheus/normalize_name.go | 8 +--- .../prometheus/normalize_name_test.go | 12 +----- receiver/prometheusreceiver/README.md | 22 +++++++++++ receiver/prometheusreceiver/config.go | 7 ++-- receiver/prometheusreceiver/config_test.go | 1 + receiver/prometheusreceiver/go.mod | 1 - .../prometheusreceiver/internal/appendable.go | 7 +++- .../internal/metricfamily.go | 10 +++-- .../internal/metricfamily_test.go | 6 +-- .../internal/transaction.go | 7 +++- .../internal/transaction_test.go | 38 +++++++++---------- .../prometheusreceiver/metrics_receiver.go | 1 + .../metrics_receiver_helper_test.go | 3 +- .../metrics_receiver_honor_timestamp_test.go | 4 +- .../metrics_receiver_labels_test.go | 20 +++++----- ...ics_receiver_metric_name_normalize_test.go | 6 +-- .../metrics_receiver_non_numerical_test.go | 6 +-- .../metrics_receiver_open_metrics_test.go | 6 +-- .../metrics_receiver_test.go | 8 ++-- .../metrics_reciever_metric_rename_test.go | 8 ++-- .../prometheusreceiver/testdata/config.yaml | 1 + 22 files changed, 124 insertions(+), 81 deletions(-) create mode 100644 .chloggen/prometheus-receiver-normalization-config.yaml diff --git a/.chloggen/prometheus-receiver-normalization-config.yaml b/.chloggen/prometheus-receiver-normalization-config.yaml new file mode 100644 index 000000000000..3e986e144de0 --- /dev/null +++ b/.chloggen/prometheus-receiver-normalization-config.yaml @@ -0,0 +1,23 @@ +# Use this changelog template to create an entry for release notes. +# If your change doesn't affect end users, such as a test fix or a tooling change, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: 'breaking' + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: prometheusreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Add the `trim_metric_suffixes` configuration option to allow enable metric suffix trimming." + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [21743, 8950] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: | + When enabled, suffixes for unit and type are trimmed from metric names. + If you previously enabled the `pkg.translator.prometheus.NormalizeName` + feature gate, you will need to enable this option to have suffixes trimmed. diff --git a/pkg/translator/prometheus/normalize_name.go b/pkg/translator/prometheus/normalize_name.go index 1a4a376aea00..da924cd424da 100644 --- a/pkg/translator/prometheus/normalize_name.go +++ b/pkg/translator/prometheus/normalize_name.go @@ -71,7 +71,7 @@ var perUnitMap = map[string]string{ "y": "year", } -var NormalizeNameGate = featuregate.GlobalRegistry().MustRegister( +var normalizeNameGate = featuregate.GlobalRegistry().MustRegister( "pkg.translator.prometheus.NormalizeName", featuregate.StageAlpha, featuregate.WithRegisterDescription("Controls whether metrics names are automatically normalized to follow Prometheus naming convention"), @@ -90,7 +90,7 @@ func BuildPromCompliantName(metric pmetric.Metric, namespace string) string { var metricName string // Full normalization following standard Prometheus naming conventions - if NormalizeNameGate.IsEnabled() { + if normalizeNameGate.IsEnabled() { return normalizeName(metric, namespace) } @@ -182,10 +182,6 @@ func normalizeName(metric pmetric.Metric, namespace string) string { // // [OpenTelemetry specs]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#metric-metadata func TrimPromSuffixes(promName string, metricType pmetric.MetricType, unit string) string { - if !NormalizeNameGate.IsEnabled() { - return promName - } - nameTokens := strings.Split(promName, "_") if len(nameTokens) == 1 { return promName diff --git a/pkg/translator/prometheus/normalize_name_test.go b/pkg/translator/prometheus/normalize_name_test.go index 3477b8eedee7..8ef01f2a4b34 100644 --- a/pkg/translator/prometheus/normalize_name_test.go +++ b/pkg/translator/prometheus/normalize_name_test.go @@ -138,8 +138,6 @@ func TestOtelReceivers(t *testing.T) { } func TestTrimPromSuffixes(t *testing.T) { - defer testutil.SetFeatureGateForTest(t, NormalizeNameGate, true)() - assert.Equal(t, "active_directory_ds_replication_network_io", TrimPromSuffixes("active_directory_ds_replication_network_io_bytes_total", pmetric.MetricTypeSum, "bytes")) assert.Equal(t, "active_directory_ds_name_cache_hit_rate", TrimPromSuffixes("active_directory_ds_name_cache_hit_rate_percent", pmetric.MetricTypeGauge, "percent")) assert.Equal(t, "active_directory_ds_ldap_bind_last_successful_time", TrimPromSuffixes("active_directory_ds_ldap_bind_last_successful_time_milliseconds", pmetric.MetricTypeGauge, "milliseconds")) @@ -170,12 +168,6 @@ func TestTrimPromSuffixes(t *testing.T) { } -func TestTrimPromSuffixesWithFeatureGateDisabled(t *testing.T) { - defer testutil.SetFeatureGateForTest(t, NormalizeNameGate, false)() - assert.Equal(t, "apache_current_connections", TrimPromSuffixes("apache_current_connections", pmetric.MetricTypeGauge, "connections")) - assert.Equal(t, "apache_requests_total", TrimPromSuffixes("apache_requests_total", pmetric.MetricTypeSum, "1")) -} - func TestNamespace(t *testing.T) { require.Equal(t, "space_test", normalizeName(createGauge("test", ""), "space")) require.Equal(t, "space_test", normalizeName(createGauge("#test", ""), "space")) @@ -220,7 +212,7 @@ func TestRemoveItem(t *testing.T) { func TestBuildPromCompliantNameWithNormalize(t *testing.T) { - defer testutil.SetFeatureGateForTest(t, NormalizeNameGate, true)() + defer testutil.SetFeatureGateForTest(t, normalizeNameGate, true)() require.Equal(t, "system_io_bytes_total", BuildPromCompliantName(createCounter("system.io", "By"), "")) require.Equal(t, "system_network_io_bytes_total", BuildPromCompliantName(createCounter("network.io", "By"), "system")) require.Equal(t, "_3_14_digits", BuildPromCompliantName(createGauge("3.14 digits", ""), "")) @@ -232,7 +224,7 @@ func TestBuildPromCompliantNameWithNormalize(t *testing.T) { func TestBuildPromCompliantNameWithoutNormalize(t *testing.T) { - defer testutil.SetFeatureGateForTest(t, NormalizeNameGate, false)() + defer testutil.SetFeatureGateForTest(t, normalizeNameGate, false)() require.Equal(t, "system_io", BuildPromCompliantName(createCounter("system.io", "By"), "")) require.Equal(t, "system_network_io", BuildPromCompliantName(createCounter("network.io", "By"), "system")) require.Equal(t, "system_network_I_O", BuildPromCompliantName(createCounter("network (I/O)", "By"), "system")) diff --git a/receiver/prometheusreceiver/README.md b/receiver/prometheusreceiver/README.md index 05ca44685719..e4eae02f025d 100644 --- a/receiver/prometheusreceiver/README.md +++ b/receiver/prometheusreceiver/README.md @@ -102,6 +102,28 @@ receivers: action: keep ``` +The prometheus receiver also supports additional top-level options: + +- **trim_metric_suffixes**: [**Experimental**] When set to true, this enables trimming unit and some counter type suffixes from metric names. For example, it would cause `singing_duration_seconds_total` to be trimmed to `singing_duration`. This can be useful when trying to restore the original metric names used in OpenTelemetry instrumentation. Defaults to false. +- **use_start_time_metric**: When set to true, this enables retrieving the start time of all counter metrics from the process_start_time_seconds metric. This is only correct if all counters on that endpoint started after the process start time, and the process is the only actor exporting the metric after the process started. It should not be used in "exporters" which export counters that may have started before the process itself. Use only if you know what you are doing, as this may result in incorrect rate calculations. Defaults to false. +- **start_time_metric_regex**: The regular expression for the start time metric, and is only applied when use_start_time_metric is enabled. Defaults to process_start_time_seconds. + +For example, + +```yaml +receivers: + prometheus: + trim_metric_suffixes: true + use_start_time_metric: true + start_time_metric_regex: foo_bar_.* + config: + scrape_configs: + - job_name: 'otel-collector' + scrape_interval: 5s + static_configs: + - targets: ['0.0.0.0:8888'] +``` + ## OpenTelemetry Operator Additional to this static job definitions this receiver allows to query a list of jobs from the OpenTelemetryOperators TargetAllocator or a compatible endpoint. diff --git a/receiver/prometheusreceiver/config.go b/receiver/prometheusreceiver/config.go index 455c758b3cd0..0827ad3f861e 100644 --- a/receiver/prometheusreceiver/config.go +++ b/receiver/prometheusreceiver/config.go @@ -32,9 +32,10 @@ const ( // Config defines configuration for Prometheus receiver. type Config struct { - PrometheusConfig *promconfig.Config `mapstructure:"-"` - BufferPeriod time.Duration `mapstructure:"buffer_period"` - BufferCount int `mapstructure:"buffer_count"` + PrometheusConfig *promconfig.Config `mapstructure:"-"` + TrimMetricSuffixes bool `mapstructure:"trim_metric_suffixes"` + BufferPeriod time.Duration `mapstructure:"buffer_period"` + BufferCount int `mapstructure:"buffer_count"` // UseStartTimeMetric enables retrieving the start time of all counter metrics // from the process_start_time_seconds metric. This is only correct if all counters on that endpoint // started after the process start time, and the process is the only actor exporting the metric after diff --git a/receiver/prometheusreceiver/config_test.go b/receiver/prometheusreceiver/config_test.go index 184c6f538c21..505a42e9942e 100644 --- a/receiver/prometheusreceiver/config_test.go +++ b/receiver/prometheusreceiver/config_test.go @@ -40,6 +40,7 @@ func TestLoadConfig(t *testing.T) { assert.Equal(t, r1.PrometheusConfig.ScrapeConfigs[0].JobName, "demo") assert.Equal(t, time.Duration(r1.PrometheusConfig.ScrapeConfigs[0].ScrapeInterval), 5*time.Second) assert.Equal(t, r1.UseStartTimeMetric, true) + assert.Equal(t, r1.TrimMetricSuffixes, true) assert.Equal(t, r1.StartTimeMetricRegex, "^(.+_)*process_start_time_seconds$") assert.Equal(t, "http://my-targetallocator-service", r1.TargetAllocator.Endpoint) diff --git a/receiver/prometheusreceiver/go.mod b/receiver/prometheusreceiver/go.mod index e4519d620626..f90d7ca27910 100644 --- a/receiver/prometheusreceiver/go.mod +++ b/receiver/prometheusreceiver/go.mod @@ -8,7 +8,6 @@ require ( github.com/golang/snappy v0.0.4 github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter v0.81.0 - github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.81.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.81.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus v0.81.0 github.com/prometheus/common v0.44.0 diff --git a/receiver/prometheusreceiver/internal/appendable.go b/receiver/prometheusreceiver/internal/appendable.go index a735a536c250..81cee2f01375 100644 --- a/receiver/prometheusreceiver/internal/appendable.go +++ b/receiver/prometheusreceiver/internal/appendable.go @@ -20,6 +20,7 @@ type appendable struct { sink consumer.Metrics metricAdjuster MetricsAdjuster useStartTimeMetric bool + trimSuffixes bool startTimeMetricRegex *regexp.Regexp externalLabels labels.Labels @@ -35,7 +36,8 @@ func NewAppendable( useStartTimeMetric bool, startTimeMetricRegex *regexp.Regexp, useCreatedMetric bool, - externalLabels labels.Labels) (storage.Appendable, error) { + externalLabels labels.Labels, + trimSuffixes bool) (storage.Appendable, error) { var metricAdjuster MetricsAdjuster if !useStartTimeMetric { metricAdjuster = NewInitialPointAdjuster(set.Logger, gcInterval, useCreatedMetric) @@ -56,9 +58,10 @@ func NewAppendable( startTimeMetricRegex: startTimeMetricRegex, externalLabels: externalLabels, obsrecv: obsrecv, + trimSuffixes: trimSuffixes, }, nil } func (o *appendable) Appender(ctx context.Context) storage.Appender { - return newTransaction(ctx, o.metricAdjuster, o.sink, o.externalLabels, o.settings, o.obsrecv) + return newTransaction(ctx, o.metricAdjuster, o.sink, o.externalLabels, o.settings, o.obsrecv, o.trimSuffixes) } diff --git a/receiver/prometheusreceiver/internal/metricfamily.go b/receiver/prometheusreceiver/internal/metricfamily.go index da8f6372aef3..71ebcaef87ce 100644 --- a/receiver/prometheusreceiver/internal/metricfamily.go +++ b/receiver/prometheusreceiver/internal/metricfamily.go @@ -301,10 +301,14 @@ func (mf *metricFamily) addSeries(seriesRef uint64, metricName string, ls labels return nil } -func (mf *metricFamily) appendMetric(metrics pmetric.MetricSlice) { +func (mf *metricFamily) appendMetric(metrics pmetric.MetricSlice, trimSuffixes bool) { metric := pmetric.NewMetric() - // Trims type's and unit's suffixes from metric name - metric.SetName(prometheus.TrimPromSuffixes(mf.name, mf.mtype, mf.metadata.Unit)) + // Trims type and unit suffixes from metric name + name := mf.name + if trimSuffixes { + name = prometheus.TrimPromSuffixes(name, mf.mtype, mf.metadata.Unit) + } + metric.SetName(name) metric.SetDescription(mf.metadata.Help) metric.SetUnit(mf.metadata.Unit) diff --git a/receiver/prometheusreceiver/internal/metricfamily_test.go b/receiver/prometheusreceiver/internal/metricfamily_test.go index fa3fded746a8..110586c7460e 100644 --- a/receiver/prometheusreceiver/internal/metricfamily_test.go +++ b/receiver/prometheusreceiver/internal/metricfamily_test.go @@ -249,7 +249,7 @@ func TestMetricGroupData_toDistributionUnitTest(t *testing.T) { require.Len(t, mp.groups, 1) sl := pmetric.NewMetricSlice() - mp.appendMetric(sl) + mp.appendMetric(sl, false) require.Equal(t, 1, sl.Len(), "Exactly one metric expected") metric := sl.At(0) @@ -537,7 +537,7 @@ func TestMetricGroupData_toSummaryUnitTest(t *testing.T) { require.Len(t, mp.groups, 1) sl := pmetric.NewMetricSlice() - mp.appendMetric(sl) + mp.appendMetric(sl, false) require.Equal(t, 1, sl.Len(), "Exactly one metric expected") metric := sl.At(0) @@ -643,7 +643,7 @@ func TestMetricGroupData_toNumberDataUnitTest(t *testing.T) { require.Len(t, mp.groups, 1) sl := pmetric.NewMetricSlice() - mp.appendMetric(sl) + mp.appendMetric(sl, false) require.Equal(t, 1, sl.Len(), "Exactly one metric expected") metric := sl.At(0) diff --git a/receiver/prometheusreceiver/internal/transaction.go b/receiver/prometheusreceiver/internal/transaction.go index 663615022c91..ca72ae7d1716 100644 --- a/receiver/prometheusreceiver/internal/transaction.go +++ b/receiver/prometheusreceiver/internal/transaction.go @@ -33,6 +33,7 @@ const ( type transaction struct { isNew bool + trimSuffixes bool ctx context.Context families map[string]*metricFamily mc scrape.MetricMetadataStore @@ -53,11 +54,13 @@ func newTransaction( sink consumer.Metrics, externalLabels labels.Labels, settings receiver.CreateSettings, - obsrecv *obsreport.Receiver) *transaction { + obsrecv *obsreport.Receiver, + trimSuffixes bool) *transaction { return &transaction{ ctx: ctx, families: make(map[string]*metricFamily), isNew: true, + trimSuffixes: trimSuffixes, sink: sink, metricAdjuster: metricAdjuster, externalLabels: externalLabels, @@ -200,7 +203,7 @@ func (t *transaction) getMetrics(resource pcommon.Resource) (pmetric.Metrics, er metrics := ils.Metrics() for _, mf := range t.families { - mf.appendMetric(metrics) + mf.appendMetric(metrics, t.trimSuffixes) } return md, nil diff --git a/receiver/prometheusreceiver/internal/transaction_test.go b/receiver/prometheusreceiver/internal/transaction_test.go index 721c0fbf8f37..088684810f2c 100644 --- a/receiver/prometheusreceiver/internal/transaction_test.go +++ b/receiver/prometheusreceiver/internal/transaction_test.go @@ -51,24 +51,24 @@ var ( ) func TestTransactionCommitWithoutAdding(t *testing.T) { - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) assert.NoError(t, tr.Commit()) } func TestTransactionRollbackDoesNothing(t *testing.T) { - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) assert.NoError(t, tr.Rollback()) } func TestTransactionUpdateMetadataDoesNothing(t *testing.T) { - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.UpdateMetadata(0, labels.New(), metadata.Metadata{}) assert.NoError(t, err) } func TestTransactionAppendNoTarget(t *testing.T) { badLabels := labels.FromStrings(model.MetricNameLabel, "counter_test") - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.Append(0, badLabels, time.Now().Unix()*1000, 1.0) assert.Error(t, err) } @@ -78,7 +78,7 @@ func TestTransactionAppendNoMetricName(t *testing.T) { model.InstanceLabel: "localhost:8080", model.JobLabel: "test2", }) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.Append(0, jobNotFoundLb, time.Now().Unix()*1000, 1.0) assert.ErrorIs(t, err, errMetricNameNotFound) @@ -86,7 +86,7 @@ func TestTransactionAppendNoMetricName(t *testing.T) { } func TestTransactionAppendEmptyMetricName(t *testing.T) { - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, consumertest.NewNop(), nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.Append(0, labels.FromMap(map[string]string{ model.InstanceLabel: "localhost:8080", model.JobLabel: "test2", @@ -97,7 +97,7 @@ func TestTransactionAppendEmptyMetricName(t *testing.T) { func TestTransactionAppendResource(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.Append(0, labels.FromMap(map[string]string{ model.InstanceLabel: "localhost:8080", model.JobLabel: "test", @@ -120,7 +120,7 @@ func TestTransactionAppendResource(t *testing.T) { func TestReceiverVersionAndNameAreAttached(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.Append(0, labels.FromMap(map[string]string{ model.InstanceLabel: "localhost:8080", model.JobLabel: "test", @@ -148,7 +148,7 @@ func TestTransactionCommitErrorWhenAdjusterError(t *testing.T) { }) sink := new(consumertest.MetricsSink) adjusterErr := errors.New("adjuster error") - tr := newTransaction(scrapeCtx, &errorAdjuster{err: adjusterErr}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &errorAdjuster{err: adjusterErr}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.Append(0, goodLabels, time.Now().Unix()*1000, 1.0) assert.NoError(t, err) assert.ErrorIs(t, tr.Commit(), adjusterErr) @@ -157,7 +157,7 @@ func TestTransactionCommitErrorWhenAdjusterError(t *testing.T) { // Ensure that we reject duplicate label keys. See https://github.com/open-telemetry/wg-prometheus/issues/44. func TestTransactionAppendDuplicateLabels(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) dupLabels := labels.FromStrings( model.InstanceLabel, "0.0.0.0:8855", @@ -175,7 +175,7 @@ func TestTransactionAppendDuplicateLabels(t *testing.T) { func TestTransactionAppendHistogramNoLe(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) goodLabels := labels.FromStrings( model.InstanceLabel, "0.0.0.0:8855", @@ -189,7 +189,7 @@ func TestTransactionAppendHistogramNoLe(t *testing.T) { func TestTransactionAppendSummaryNoQuantile(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) goodLabels := labels.FromStrings( model.InstanceLabel, "0.0.0.0:8855", @@ -203,7 +203,7 @@ func TestTransactionAppendSummaryNoQuantile(t *testing.T) { func TestAppendExemplarWithNoMetricName(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) labels := labels.FromStrings( model.InstanceLabel, "0.0.0.0:8855", @@ -216,7 +216,7 @@ func TestAppendExemplarWithNoMetricName(t *testing.T) { func TestAppendExemplarWithEmptyMetricName(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) labels := labels.FromStrings( model.InstanceLabel, "0.0.0.0:8855", @@ -229,7 +229,7 @@ func TestAppendExemplarWithEmptyMetricName(t *testing.T) { func TestAppendExemplarWithDuplicateLabels(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) labels := labels.FromStrings( model.InstanceLabel, "0.0.0.0:8855", @@ -245,7 +245,7 @@ func TestAppendExemplarWithDuplicateLabels(t *testing.T) { func TestAppendExemplarWithoutAddingMetric(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) labels := labels.FromStrings( model.InstanceLabel, "0.0.0.0:8855", @@ -259,7 +259,7 @@ func TestAppendExemplarWithoutAddingMetric(t *testing.T) { func TestAppendExemplarWithNoLabels(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.AppendExemplar(0, nil, exemplar.Exemplar{Value: 0}) assert.Equal(t, errNoJobInstance, err) @@ -267,7 +267,7 @@ func TestAppendExemplarWithNoLabels(t *testing.T) { func TestAppendExemplarWithEmptyLabelArray(t *testing.T) { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) _, err := tr.AppendExemplar(0, []labels.Label{}, exemplar.Exemplar{Value: 0}) assert.Equal(t, errNoJobInstance, err) @@ -1366,7 +1366,7 @@ func (tt buildTestData) run(t *testing.T) { st := ts for i, page := range tt.inputs { sink := new(consumertest.MetricsSink) - tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t)) + tr := newTransaction(scrapeCtx, &startTimeAdjuster{startTime: startTimestamp}, sink, nil, receivertest.NewNopCreateSettings(), nopObsRecv(t), false) for _, pt := range page.pts { // set ts for testing pt.t = st diff --git a/receiver/prometheusreceiver/metrics_receiver.go b/receiver/prometheusreceiver/metrics_receiver.go index a05b79762994..70b1c6af8774 100644 --- a/receiver/prometheusreceiver/metrics_receiver.go +++ b/receiver/prometheusreceiver/metrics_receiver.go @@ -260,6 +260,7 @@ func (r *pReceiver) initPrometheusComponents(ctx context.Context, host component startTimeMetricRegex, useCreatedMetricGate.IsEnabled(), r.cfg.PrometheusConfig.GlobalConfig.ExternalLabels, + r.cfg.TrimMetricSuffixes, ) if err != nil { return err diff --git a/receiver/prometheusreceiver/metrics_receiver_helper_test.go b/receiver/prometheusreceiver/metrics_receiver_helper_test.go index dd28c7907c4d..d7d1dbbebc7c 100644 --- a/receiver/prometheusreceiver/metrics_receiver_helper_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_helper_test.go @@ -576,7 +576,7 @@ func compareSummary(count uint64, sum float64, quantiles [][]float64) summaryPoi } // starts prometheus receiver with custom config, retrieves metrics from MetricsSink -func testComponent(t *testing.T, targets []*testData, useStartTimeMetric bool, startTimeMetricRegex string, cfgMuts ...func(*promcfg.Config)) { +func testComponent(t *testing.T, targets []*testData, useStartTimeMetric bool, trimMetricSuffixes bool, startTimeMetricRegex string, cfgMuts ...func(*promcfg.Config)) { ctx := context.Background() mp, cfg, err := setupMockPrometheus(targets...) for _, cfgMut := range cfgMuts { @@ -590,6 +590,7 @@ func testComponent(t *testing.T, targets []*testData, useStartTimeMetric bool, s PrometheusConfig: cfg, UseStartTimeMetric: useStartTimeMetric, StartTimeMetricRegex: startTimeMetricRegex, + TrimMetricSuffixes: trimMetricSuffixes, }, cms) require.NoError(t, receiver.Start(ctx, componenttest.NewNopHost())) diff --git a/receiver/prometheusreceiver/metrics_receiver_honor_timestamp_test.go b/receiver/prometheusreceiver/metrics_receiver_honor_timestamp_test.go index a14146ab1ddc..951934d646dd 100644 --- a/receiver/prometheusreceiver/metrics_receiver_honor_timestamp_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_honor_timestamp_test.go @@ -150,7 +150,7 @@ func TestHonorTimeStampsWithTrue(t *testing.T) { }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } // TestHonorTimeStampsWithFalse validates that with honor_timestamp config set to false, @@ -168,7 +168,7 @@ func TestHonorTimeStampsWithFalse(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { for _, scrapeConfig := range cfg.ScrapeConfigs { scrapeConfig.HonorTimestamps = false } diff --git a/receiver/prometheusreceiver/metrics_receiver_labels_test.go b/receiver/prometheusreceiver/metrics_receiver_labels_test.go index ce48709576e5..73ee1ae69628 100644 --- a/receiver/prometheusreceiver/metrics_receiver_labels_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_labels_test.go @@ -29,7 +29,7 @@ func TestExternalLabels(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { cfg.GlobalConfig.ExternalLabels = labels.FromStrings("key", "value") }) } @@ -119,7 +119,7 @@ func TestLabelLimitConfig(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { // set label limit in scrape_config for _, scrapeCfg := range cfg.ScrapeConfigs { scrapeCfg.LabelLimit = 5 @@ -242,7 +242,7 @@ func TestLabelNameLimitConfig(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { // set label limit in scrape_config for _, scrapeCfg := range cfg.ScrapeConfigs { scrapeCfg.LabelNameLengthLimit = 20 @@ -278,7 +278,7 @@ func TestLabelValueLimitConfig(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { // set label name limit in scrape_config for _, scrapeCfg := range cfg.ScrapeConfigs { scrapeCfg.LabelValueLengthLimit = 25 @@ -450,7 +450,7 @@ func TestEmptyLabelValues(t *testing.T) { validateFunc: verifyEmptyLabelValuesTarget2, }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } const honorLabelsTarget = ` @@ -541,7 +541,7 @@ func TestEmptyLabels(t *testing.T) { validateFunc: verifyEmptyLabelsTarget1, }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func TestHonorLabelsFalseConfig(t *testing.T) { @@ -555,7 +555,7 @@ func TestHonorLabelsFalseConfig(t *testing.T) { }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func verifyHonorLabelsTrue(t *testing.T, td *testData, rms []pmetric.ResourceMetrics) { @@ -597,7 +597,7 @@ func TestHonorLabelsTrueConfig(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { // set label name limit in scrape_config for _, scrapeCfg := range cfg.ScrapeConfigs { scrapeCfg.HonorLabels = true @@ -623,7 +623,7 @@ func TestRelabelJobInstance(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { for _, scrapeConfig := range cfg.ScrapeConfigs { scrapeConfig.MetricRelabelConfigs = []*relabel.Config{ { @@ -692,7 +692,7 @@ func TestTargetInfoResourceAttributes(t *testing.T) { }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func verifyTargetInfoResourceAttributes(t *testing.T, td *testData, rms []pmetric.ResourceMetrics) { diff --git a/receiver/prometheusreceiver/metrics_receiver_metric_name_normalize_test.go b/receiver/prometheusreceiver/metrics_receiver_metric_name_normalize_test.go index 1f3add13f795..9cb4274d7650 100644 --- a/receiver/prometheusreceiver/metrics_receiver_metric_name_normalize_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_metric_name_normalize_test.go @@ -8,9 +8,6 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/pdata/pmetric" - - "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/testutil" - "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus" ) var normalizeMetric = `# HELP http_connected connected clients @@ -36,7 +33,6 @@ foo_gauge_seconds{method="get",port="6380"} 5 // TestMetricNormalize validates that type's and unit's suffixes are correctly trimmed. func TestMetricNormalize(t *testing.T) { - defer testutil.SetFeatureGateForTest(t, prometheus.NormalizeNameGate, true)() targets := []*testData{ { name: "target1", @@ -48,7 +44,7 @@ func TestMetricNormalize(t *testing.T) { }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, true, "") } func verifyNormalizeMetric(t *testing.T, td *testData, resourceMetrics []pmetric.ResourceMetrics) { diff --git a/receiver/prometheusreceiver/metrics_receiver_non_numerical_test.go b/receiver/prometheusreceiver/metrics_receiver_non_numerical_test.go index 49f60522b80e..926760237f78 100644 --- a/receiver/prometheusreceiver/metrics_receiver_non_numerical_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_non_numerical_test.go @@ -70,7 +70,7 @@ func TestStaleNaNs(t *testing.T) { validateScrapes: true, }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func verifyStaleNaNs(t *testing.T, td *testData, resourceMetrics []pmetric.ResourceMetrics) { @@ -244,7 +244,7 @@ func TestNormalNaNs(t *testing.T) { validateFunc: verifyNormalNaNs, }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func verifyNormalNaNs(t *testing.T, td *testData, resourceMetrics []pmetric.ResourceMetrics) { @@ -328,7 +328,7 @@ func TestInfValues(t *testing.T) { validateFunc: verifyInfValues, }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func verifyInfValues(t *testing.T, td *testData, resourceMetrics []pmetric.ResourceMetrics) { diff --git a/receiver/prometheusreceiver/metrics_receiver_open_metrics_test.go b/receiver/prometheusreceiver/metrics_receiver_open_metrics_test.go index 34072d2bbff3..b1c7913f2fe6 100644 --- a/receiver/prometheusreceiver/metrics_receiver_open_metrics_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_open_metrics_test.go @@ -70,7 +70,7 @@ func TestOpenMetricsPositive(t *testing.T) { targets = append(targets, testData) } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func verifyNegativeTarget(t *testing.T, td *testData, mds []pmetric.ResourceMetrics) { @@ -103,7 +103,7 @@ func TestOpenMetricsNegative(t *testing.T) { targets = append(targets, testData) } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } // reads test data from testdata/openmetrics directory @@ -173,7 +173,7 @@ func TestInfoStatesetMetrics(t *testing.T) { }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } diff --git a/receiver/prometheusreceiver/metrics_receiver_test.go b/receiver/prometheusreceiver/metrics_receiver_test.go index 3d5cf6146fc2..805659627297 100644 --- a/receiver/prometheusreceiver/metrics_receiver_test.go +++ b/receiver/prometheusreceiver/metrics_receiver_test.go @@ -1274,7 +1274,7 @@ func TestCoreMetricsEndToEnd(t *testing.T) { validateScrapes: true, }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } var startTimeMetricPage = ` @@ -1361,7 +1361,7 @@ func TestStartTimeMetric(t *testing.T) { validateFunc: verifyStartTimeMetricPage, }, } - testComponent(t, targets, true, "") + testComponent(t, targets, true, false, "") } var startTimeMetricRegexPage = ` @@ -1410,7 +1410,7 @@ func TestStartTimeMetricRegex(t *testing.T) { validateFunc: verifyStartTimeMetricPage, }, } - testComponent(t, targets, true, "^(.+_)*process_start_time_seconds$") + testComponent(t, targets, true, false, "^(.+_)*process_start_time_seconds$") } // metric type is defined as 'untyped' in the first metric @@ -1439,7 +1439,7 @@ func TestUntypedMetrics(t *testing.T) { }, } - testComponent(t, targets, false, "") + testComponent(t, targets, false, false, "") } func verifyUntypedMetrics(t *testing.T, td *testData, resourceMetrics []pmetric.ResourceMetrics) { diff --git a/receiver/prometheusreceiver/metrics_reciever_metric_rename_test.go b/receiver/prometheusreceiver/metrics_reciever_metric_rename_test.go index 56a4bd09ea86..70c945cba4ab 100644 --- a/receiver/prometheusreceiver/metrics_reciever_metric_rename_test.go +++ b/receiver/prometheusreceiver/metrics_reciever_metric_rename_test.go @@ -47,7 +47,7 @@ func TestMetricRenaming(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { for _, scrapeConfig := range cfg.ScrapeConfigs { scrapeConfig.MetricRelabelConfigs = []*relabel.Config{ { @@ -90,7 +90,7 @@ func TestMetricRenamingKeepAction(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { for _, scrapeConfig := range cfg.ScrapeConfigs { scrapeConfig.MetricRelabelConfigs = []*relabel.Config{ { @@ -229,7 +229,7 @@ func TestLabelRenaming(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { for _, scrapeConfig := range cfg.ScrapeConfigs { scrapeConfig.MetricRelabelConfigs = []*relabel.Config{ { @@ -355,7 +355,7 @@ func TestLabelRenamingKeepAction(t *testing.T) { }, } - testComponent(t, targets, false, "", func(cfg *promcfg.Config) { + testComponent(t, targets, false, false, "", func(cfg *promcfg.Config) { for _, scrapeConfig := range cfg.ScrapeConfigs { scrapeConfig.MetricRelabelConfigs = []*relabel.Config{ { diff --git a/receiver/prometheusreceiver/testdata/config.yaml b/receiver/prometheusreceiver/testdata/config.yaml index f767602afcc5..db0876ad0710 100644 --- a/receiver/prometheusreceiver/testdata/config.yaml +++ b/receiver/prometheusreceiver/testdata/config.yaml @@ -2,6 +2,7 @@ prometheus: prometheus/customname: buffer_period: 234 buffer_count: 45 + trim_metric_suffixes: true use_start_time_metric: true start_time_metric_regex: '^(.+_)*process_start_time_seconds$' target_allocator: