diff --git a/CHANGELOG.md b/CHANGELOG.md index 0058f158ee0..14bcefcba8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [ENHANCEMENT] TraceQL search and metrics performance increase [#5280](https://github.com/grafana/tempo/pull/5280) (@mdisibio) * [ENHANCEMENT] Align traceql attribute struct for better performance [#5240](https://github.com/grafana/tempo/pull/5240) (@mdisibio) * [ENHANCEMENT] Enable HTTP writes in the multi-tenant example [#5297](https://github.com/grafana/tempo/pull/5297) +* [ENHANCEMENT] Drop invalid prometheus label names in spanmetrics processor [#5122](https://github.com/grafana/tempo/pull/5122) (@KyriosGN0) * [BUGFIX] Add nil check to partitionAssignmentVar [#5198](https://github.com/grafana/tempo/pull/5198) (@mapno) * [BUGFIX] Correct instant query calculation [#5252](https://github.com/grafana/tempo/pull/5252) (@ruslan-mikhailov) @@ -23,8 +24,8 @@ * [CHANGE] **BREAKING CHANGE** Change default http-listen-port from 80 to 3200 [#4960](https://github.com/grafana/tempo/pull/4960) (@martialblog) * [CHANGE] **BREAKING CHANGE** Upgrade OTEL Collector to v0.122.1. The `name` dimension from `tempo_receiver_accepted_span` and `tempo_receiver_refused_spans` changes from `tempo/jaeger_receiver` to `jaeger/jaeger_receiver`. [#4893](https://github.com/grafana/tempo/pull/4893) (@javiermolinar) * [CHANGE] **BREAKING CHANGE** Convert SLO metric `query_frontend_bytes_processed_per_second` from a histogram to a counter as it's more performant. [#4748](https://github.com/grafana/tempo/pull/4748) (@carles-grafana) -* [CHANGE] **BREAKING CHANGE** Remove tempo serverless. - The following configuration options are no longer valid. If they are in your tempo config, remove them. +* [CHANGE] **BREAKING CHANGE** Remove tempo serverless. + The following configuration options are no longer valid. If they are in your tempo config, remove them. ``` querier: search: @@ -60,7 +61,7 @@ * [ENHANCEMENT] Add throughput SLO and metrics for the TraceByID endpoint. Configurable using the `throughput_bytes_slo` field. It populates the `op="traces"` label in slo and throughput metrics. [#4668](https://github.com/grafana/tempo/pull/4668) (@carles-grafana) * [ENHANCEMENT] Add ability to add artificial delay to push requests [#4716](https://github.com/grafana/tempo/pull/4716) [#4899](https://github.com/grafana/tempo/pull/4899) [#5035](https://github.com/grafana/tempo/pull/5035) (@yvrhdn, @mapno) * [ENHANCEMENT] tempo-vulture now generates spans with a parent, instead of only root spans [#5154](https://github.com/grafana/tempo/pull/5154) (@carles-grafana) -* [ENHANCEMENT] Add default mutex and blocking values. [#4979](https://github.com/grafana/tempo/pull/4979) (@mattdurham) +* [ENHANCEMENT] Add default mutex and blocking values. [#4979](https://github.com/grafana/tempo/pull/4979) (@mattdurham) * [ENHANCEMENT] Improve Tempo build options [#4755](https://github.com/grafana/tempo/pull/4755) (@stoewer) * [ENHANCEMENT] Rewrite traces using rebatching [#4690](https://github.com/grafana/tempo/pull/4690) (@stoewer @joe-elliott) * [ENHANCEMENT] Reorder span iterators [#4754](https://github.com/grafana/tempo/pull/4754) (@stoewer) @@ -77,7 +78,7 @@ * [ENHANCEMENT] Rhythm: add block builder to resources dashboard [#4556](https://github.com/grafana/tempo/pull/4669) (@javiermolinar) * [ENHANCEMENT] Upgrade prometheus to version 3.1.0 [#4805](https://github.com/grafana/tempo/pull/4805) (@javiermolinar) * [ENHANCEMENT] Update dskit to latest version [#4681](https://github.com/grafana/tempo/pull/4681) (@javiermolinar) [#4865](https://github.com/grafana/tempo/pull/4865) (@javiermolinar) -* [ENHANCEMENT] Increase query-frontend default batch size [#4844](https://github.com/grafana/tempo/pull/4844) (@javiermolinar) +* [ENHANCEMENT] Increase query-frontend default batch size [#4844](https://github.com/grafana/tempo/pull/4844) (@javiermolinar) * [ENHANCEMENT] Improve TraceQL perf by reverting EqualRowNumber to an inlineable function.[#4705](https://github.com/grafana/tempo/pull/4705) (@joe-elliott) * [ENHANCEMENT] Rhythm: Implement MaxBytesPerCycle [#4835](https://github.com/grafana/tempo/pull/4835) (@javiermolinar) * [ENHANCEMENT] Rhythm: fair partition consumption in blockbuilders [#4655](https://github.com/grafana/tempo/pull/4655) (@javiermolinar) diff --git a/modules/generator/processor/spanmetrics/spanmetrics.go b/modules/generator/processor/spanmetrics/spanmetrics.go index 01d6ff5fe24..f08fa6dcb85 100644 --- a/modules/generator/processor/spanmetrics/spanmetrics.go +++ b/modules/generator/processor/spanmetrics/spanmetrics.go @@ -80,7 +80,7 @@ func New(cfg Config, reg registry.Registry, filteredSpansCounter, invalidUTF8Cou labels = append(labels, SanitizeLabelNameWithCollisions(m.Name, intrinsicLabels, c.Get)) } - err := validateLabelValues(labels) + err := validateUTF8LabelValues(labels) if err != nil { return nil, err } @@ -213,7 +213,7 @@ func (p *Processor) aggregateMetricsForSpan(svcName string, jobName string, inst spanMultiplier := processor_util.GetSpanMultiplier(p.Cfg.SpanMultiplierKey, span, rs) - err := validateLabelValues(labelValues) + err := validateUTF8LabelValues(labelValues) if err != nil { p.invalidUTF8Counter.Inc() return @@ -261,7 +261,7 @@ func (p *Processor) aggregateMetricsForSpan(svcName string, jobName string, inst } } -func validateLabelValues(v []string) error { +func validateUTF8LabelValues(v []string) error { for _, value := range v { if !utf8.ValidString(value) { return fmt.Errorf("invalid utf8 string: %s", value) @@ -280,7 +280,7 @@ func GetTargetInfoAttributesValues(keys, values *[]string, attributes []*v1_comm // Skip empty string keys, which are out of spec but // technically possible in the proto. These will cause // issues downstream for metrics datasources - if key == "" { + if key == "" || (key[0] >= '0' && key[0] <= '9') { continue } if key != "service.name" && key != "service.namespace" && key != "service.instance.id" && !slices.Contains(exclude, key) { diff --git a/modules/generator/processor/spanmetrics/spanmetrics_test.go b/modules/generator/processor/spanmetrics/spanmetrics_test.go index 36516d94eaa..119cd612f9a 100644 --- a/modules/generator/processor/spanmetrics/spanmetrics_test.go +++ b/modules/generator/processor/spanmetrics/spanmetrics_test.go @@ -35,13 +35,13 @@ func TestSpanMetrics(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -73,14 +73,14 @@ func TestSpanMetrics(t *testing.T) { func TestSpanMetricsTargetInfoEnabled(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} cfg.EnableTargetInfo = true - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -139,7 +139,6 @@ func TestSpanMetrics_dimensions(t *testing.T) { name: "Valid labels", dimensions: []string{ "valid_label_123", // underscores - "12345", // numeric only "_underscore_first", }, expectedCount: 10.0, @@ -154,7 +153,6 @@ func TestSpanMetrics_dimensions(t *testing.T) { "status_code": "STATUS_CODE_OK", "status_message": "OK", "valid_label_123": "", - "12345": "", "_underscore_first": "", }, }, @@ -188,7 +186,7 @@ func TestSpanMetrics_dimensions(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) @@ -197,7 +195,7 @@ func TestSpanMetrics_dimensions(t *testing.T) { cfg.IntrinsicDimensions.StatusMessage = true cfg.Dimensions = tc.dimensions - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -234,7 +232,7 @@ func TestSpanMetrics_collisions(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) @@ -242,7 +240,7 @@ func TestSpanMetrics_collisions(t *testing.T) { cfg.Dimensions = []string{"span.kind", "span_name"} cfg.IntrinsicDimensions.SpanKind = false - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -282,14 +280,14 @@ func TestSpanMetrics_collisions(t *testing.T) { func TestJobLabelWithNamespaceAndInstanceID(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} cfg.EnableTargetInfo = true - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -330,7 +328,7 @@ func TestJobLabelWithNamespaceAndInstanceID(t *testing.T) { func TestSpanMetrics_applyFilterPolicy(t *testing.T) { filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cases := []struct { filterPolicies []filterconfig.FilterPolicy @@ -421,7 +419,7 @@ func TestSpanMetrics_applyFilterPolicy(t *testing.T) { cfg.FilterPolicies = tc.filterPolicies testRegistry := registry.NewTestRegistry() - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -475,14 +473,14 @@ func TestJobLabelWithNamespaceAndNoServiceName(t *testing.T) { // but service will still be there testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} cfg.EnableTargetInfo = true - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -528,14 +526,14 @@ func TestJobLabelWithNamespaceAndNoServiceName(t *testing.T) { func TestLabelsWithDifferentBatches(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} cfg.EnableTargetInfo = true - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -607,14 +605,14 @@ func TestTargetInfoEnabled(t *testing.T) { // if the only labels are job and instance then target_info should not exist testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.EnableTargetInfo = true cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -660,14 +658,14 @@ func TestTargetInfoEnabled(t *testing.T) { func TestTargetInfoDisabled(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.EnableTargetInfo = false cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -709,14 +707,14 @@ func TestTargetInfoDisabled(t *testing.T) { func TestTargetInfoWithEmptyKey(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.EnableTargetInfo = true cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -760,7 +758,7 @@ func TestTargetInfoWithExclusion(t *testing.T) { // if the only labels are job and instance then target_info should not exist testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) @@ -768,7 +766,7 @@ func TestTargetInfoWithExclusion(t *testing.T) { cfg.TargetInfoExcludedDimensions = []string{"container", "container.id"} cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -825,14 +823,14 @@ func TestTargetInfoSanitizeLabelName(t *testing.T) { // if the only labels are job and instance then target_info should not exist testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.EnableTargetInfo = true cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -880,14 +878,14 @@ func TestTargetInfoWithJobAndInstanceOnly(t *testing.T) { // if the only labels are job and instance then target_info should not exist testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} cfg.EnableTargetInfo = true - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -922,13 +920,13 @@ func TestTargetInfoNoJobAndNoInstance(t *testing.T) { // if both job and instance are missing, target info should not exist testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -970,14 +968,14 @@ func TestTargetInfoNoJobAndNoInstance(t *testing.T) { func TestTargetInfoWithDifferentBatches(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.EnableTargetInfo = true cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -1059,7 +1057,7 @@ func TestTargetInfoWithDifferentBatches(t *testing.T) { func TestSpanMetricsDimensionMapping(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) @@ -1074,7 +1072,7 @@ func TestSpanMetricsDimensionMapping(t *testing.T) { }, } - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -1119,7 +1117,7 @@ func TestSpanMetricsDimensionMapping(t *testing.T) { func TestSpanMetricsDimensionMappingMissingLabels(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) @@ -1147,7 +1145,7 @@ func TestSpanMetricsDimensionMappingMissingLabels(t *testing.T) { }, } - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -1198,13 +1196,13 @@ func TestSpanMetricsDimensionMappingMissingLabels(t *testing.T) { func TestSpanMetricsNegativeLatency(t *testing.T) { testRegistry := registry.NewTestRegistry() filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.HistogramBuckets = []float64{0.5, 1} - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(t, err) defer p.Shutdown(context.Background()) @@ -1330,14 +1328,14 @@ func BenchmarkSpanMetrics_applyFilterPolicyMedium(b *testing.B) { func benchmarkFilterPolicy(b *testing.B, policies []filterconfig.FilterPolicy, batch *trace_v1.ResourceSpans) { filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") - invalidSpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") testRegistry := registry.NewTestRegistry() cfg := Config{} cfg.RegisterFlagsAndApplyDefaults("", nil) cfg.FilterPolicies = policies - p, err := New(cfg, testRegistry, filteredSpansCounter, invalidSpanLabelsCounter) + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) require.NoError(b, err) defer p.Shutdown(context.Background()) b.ResetTimer() @@ -1345,3 +1343,43 @@ func benchmarkFilterPolicy(b *testing.B, policies []filterconfig.FilterPolicy, b p.PushSpans(context.Background(), &tempopb.PushSpansRequest{Batches: []*trace_v1.ResourceSpans{batch}}) } } + +func TestTargetInfoSkipsLabelsStartingWithNumber(t *testing.T) { + testRegistry := registry.NewTestRegistry() + filteredSpansCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "filtered") + invalidUTF8SpanLabelsCounter := metricSpansDiscarded.WithLabelValues("test-tenant", "invalid_utf8") + + cfg := Config{} + cfg.RegisterFlagsAndApplyDefaults("", nil) + cfg.EnableTargetInfo = true + cfg.HistogramBuckets = []float64{0.5, 1} + + p, err := New(cfg, testRegistry, filteredSpansCounter, invalidUTF8SpanLabelsCounter) + require.NoError(t, err) + defer p.Shutdown(context.Background()) + + batch := test.MakeBatch(1, nil) + batch.Resource.Attributes = []*common_v1.KeyValue{ + { + Key: "service.name", + Value: &common_v1.AnyValue{Value: &common_v1.AnyValue_StringValue{StringValue: "test-service"}}, + }, + { + Key: "5badlabel", + Value: &common_v1.AnyValue{Value: &common_v1.AnyValue_StringValue{StringValue: "should-be-ignored"}}, + }, + { + Key: "good_label", + Value: &common_v1.AnyValue{Value: &common_v1.AnyValue_StringValue{StringValue: "should-appear"}}, + }, + } + + p.PushSpans(context.Background(), &tempopb.PushSpansRequest{Batches: []*trace_v1.ResourceSpans{batch}}) + // The produced target_info metric should not contain the bad label + lbls := labels.FromMap(map[string]string{ + "job": "test-service", + "good_label": "should-appear", + }) + + assert.Equal(t, 1.0, testRegistry.Query("traces_target_info", lbls)) +}