From 07e26dd2329e038360a73ad3edc42820994a600e Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Wed, 12 Jul 2023 11:29:00 -0600 Subject: [PATCH 1/8] add otel_scope_info metric to prometheus remote write exporter --- .../prometheusremotewriteexporter/README.md | 2 + .../prometheusremotewriteexporter/config.go | 8 + .../prometheusremotewriteexporter/exporter.go | 1 + .../prometheusremotewriteexporter/factory.go | 3 + .../prometheusremotewrite/helper.go | 94 ++++++++-- .../prometheusremotewrite/helper_test.go | 171 +++++++++++++++++- .../prometheusremotewrite/histograms.go | 2 + .../prometheusremotewrite/histograms_test.go | 1 + .../prometheusremotewrite/metrics_to_prw.go | 12 +- .../number_data_points.go | 5 + .../number_data_points_test.go | 2 + 11 files changed, 283 insertions(+), 18 deletions(-) diff --git a/exporter/prometheusremotewriteexporter/README.md b/exporter/prometheusremotewriteexporter/README.md index 33cc93fa0261..e8dfcc4b3138 100644 --- a/exporter/prometheusremotewriteexporter/README.md +++ b/exporter/prometheusremotewriteexporter/README.md @@ -58,6 +58,8 @@ The following settings can be optionally configured: - `enabled` (default = false): If `enabled` is `true`, all the resource attributes will be converted to metric labels by default. - `target_info`: customize `target_info` metric - `enabled` (default = true): If `enabled` is `true`, a `target_info` metric will be generated for each resource metric (see https://github.com/open-telemetry/opentelemetry-specification/pull/2381). +- `scope_info`: customize `otel_scope_info` metric + - `enabled` (default = true): If `enabled` is `true`, a `otel_scope_info` metric will be generated for each instrumentation scope metric (see https://github.com/open-telemetry/opentelemetry-specification/pull/2703). - `export_created_metric`: - `enabled` (default = false): If `enabled` is `true`, a `_created` metric is exported for Summary, Histogram, and Monotonic Sum metric points if diff --git a/exporter/prometheusremotewriteexporter/config.go b/exporter/prometheusremotewriteexporter/config.go index f70b635ad8d2..93b67119bbdb 100644 --- a/exporter/prometheusremotewriteexporter/config.go +++ b/exporter/prometheusremotewriteexporter/config.go @@ -40,6 +40,9 @@ type Config struct { // TargetInfo allows customizing the target_info metric TargetInfo *TargetInfo `mapstructure:"target_info,omitempty"` + // ScopeInfo allows customizing the scope_info metric + ScopeInfo *ScopeInfo `mapstructure:"scope_info,omitempty"` + // CreatedMetric allows customizing creation of _created metrics CreatedMetric *CreatedMetric `mapstructure:"export_created_metric,omitempty"` } @@ -54,6 +57,11 @@ type TargetInfo struct { Enabled bool `mapstructure:"enabled"` } +type ScopeInfo struct { + // Enabled if false the otel_scope_info metric is not generated by the exporter + Enabled bool `mapstructure:"enabled"` +} + // RemoteWriteQueue allows to configure the remote write queue. type RemoteWriteQueue struct { // Enabled if false the queue is not enabled, the export requests diff --git a/exporter/prometheusremotewriteexporter/exporter.go b/exporter/prometheusremotewriteexporter/exporter.go index 102110994296..a16e1b722bcc 100644 --- a/exporter/prometheusremotewriteexporter/exporter.go +++ b/exporter/prometheusremotewriteexporter/exporter.go @@ -72,6 +72,7 @@ func newPRWExporter(cfg *Config, set exporter.CreateSettings) (*prwExporter, err Namespace: cfg.Namespace, ExternalLabels: sanitizedLabels, DisableTargetInfo: !cfg.TargetInfo.Enabled, + DisableScopeInfo: !cfg.ScopeInfo.Enabled, ExportCreatedMetric: cfg.CreatedMetric.Enabled, }, } diff --git a/exporter/prometheusremotewriteexporter/factory.go b/exporter/prometheusremotewriteexporter/factory.go index bfbd1b6e222f..d7f87cfc6693 100644 --- a/exporter/prometheusremotewriteexporter/factory.go +++ b/exporter/prometheusremotewriteexporter/factory.go @@ -97,6 +97,9 @@ func createDefaultConfig() component.Config { TargetInfo: &TargetInfo{ Enabled: true, }, + ScopeInfo: &ScopeInfo{ + Enabled: true, + }, CreatedMetric: &CreatedMetric{ Enabled: false, }, diff --git a/pkg/translator/prometheusremotewrite/helper.go b/pkg/translator/prometheusremotewrite/helper.go index b1ad78fc0c7e..5a6450924385 100644 --- a/pkg/translator/prometheusremotewrite/helper.go +++ b/pkg/translator/prometheusremotewrite/helper.go @@ -44,6 +44,9 @@ const ( spanIDKey = "span_id" infoType = "info" targetMetricName = "target_info" + scopeMetricName = "otel_scope_info" + scopeAttrName = "otel_scope_name" + scopeAttrVersion = "otel_scope_version" ) type bucketBoundsData struct { @@ -148,7 +151,13 @@ func timeSeriesSignature(datatype string, labels *[]prompb.Label) string { // createAttributes creates a slice of Cortex Label with OTLP attributes and pairs of string values. // Unpaired string value is ignored. String pairs overwrites OTLP labels if collision happens, and the overwrite is // logged. Resultant label names are sanitized. -func createAttributes(resource pcommon.Resource, attributes pcommon.Map, externalLabels map[string]string, extras ...string) []prompb.Label { +func createAttributes( + resource pcommon.Resource, + scope pcommon.InstrumentationScope, + attributes pcommon.Map, + externalLabels map[string]string, + extras ...string, +) []prompb.Label { // map ensures no duplicate label name l := map[string]prompb.Label{} @@ -204,6 +213,14 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, externa } } + // add scope name/version labels + if len(scope.Name()) > 0 { + extras = append(extras, scopeAttrName, scope.Name()) + } + if len(scope.Version()) > 0 { + extras = append(extras, scopeAttrVersion, scope.Version()) + } + for i := 0; i < len(extras); i += 2 { if i+1 >= len(extras) { break @@ -249,7 +266,14 @@ func isValidAggregationTemporality(metric pmetric.Metric) bool { // addSingleHistogramDataPoint converts pt to 2 + min(len(ExplicitBounds), len(BucketCount)) + 1 samples. It // ignore extra buckets if len(ExplicitBounds) > len(BucketCounts) -func addSingleHistogramDataPoint(pt pmetric.HistogramDataPoint, resource pcommon.Resource, metric pmetric.Metric, settings Settings, tsMap map[string]*prompb.TimeSeries) { +func addSingleHistogramDataPoint( + pt pmetric.HistogramDataPoint, + resource pcommon.Resource, + scope pcommon.InstrumentationScope, + metric pmetric.Metric, + settings Settings, + tsMap map[string]*prompb.TimeSeries, +) { timestamp := convertTimeStamp(pt.Timestamp()) // sum, count, and buckets of the histogram should append suffix to baseName baseName := prometheustranslator.BuildPromCompliantName(metric, settings.Namespace) @@ -266,7 +290,7 @@ func addSingleHistogramDataPoint(pt pmetric.HistogramDataPoint, resource pcommon sum.Value = math.Float64frombits(value.StaleNaN) } - sumlabels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+sumStr) + sumlabels := createAttributes(resource, scope, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+sumStr) addSample(tsMap, sum, sumlabels, metric.Type().String()) } @@ -280,7 +304,7 @@ func addSingleHistogramDataPoint(pt pmetric.HistogramDataPoint, resource pcommon count.Value = math.Float64frombits(value.StaleNaN) } - countlabels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+countStr) + countlabels := createAttributes(resource, scope, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+countStr) addSample(tsMap, count, countlabels, metric.Type().String()) // cumulative count for conversion to cumulative histogram @@ -302,7 +326,7 @@ func addSingleHistogramDataPoint(pt pmetric.HistogramDataPoint, resource pcommon bucket.Value = math.Float64frombits(value.StaleNaN) } boundStr := strconv.FormatFloat(bound, 'f', -1, 64) - labels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+bucketStr, leStr, boundStr) + labels := createAttributes(resource, scope, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+bucketStr, leStr, boundStr) sig := addSample(tsMap, bucket, labels, metric.Type().String()) bucketBounds = append(bucketBounds, bucketBoundsData{sig: sig, bound: bound}) @@ -316,7 +340,7 @@ func addSingleHistogramDataPoint(pt pmetric.HistogramDataPoint, resource pcommon } else { infBucket.Value = float64(pt.Count()) } - infLabels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+bucketStr, leStr, pInfStr) + infLabels := createAttributes(resource, scope, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+bucketStr, leStr, pInfStr) sig := addSample(tsMap, infBucket, infLabels, metric.Type().String()) bucketBounds = append(bucketBounds, bucketBoundsData{sig: sig, bound: math.Inf(1)}) @@ -327,6 +351,7 @@ func addSingleHistogramDataPoint(pt pmetric.HistogramDataPoint, resource pcommon if settings.ExportCreatedMetric && startTimestamp != 0 { createdLabels := createAttributes( resource, + scope, pt.Attributes(), settings.ExternalLabels, nameStr, @@ -438,8 +463,14 @@ func maxTimestamp(a, b pcommon.Timestamp) pcommon.Timestamp { } // addSingleSummaryDataPoint converts pt to len(QuantileValues) + 2 samples. -func addSingleSummaryDataPoint(pt pmetric.SummaryDataPoint, resource pcommon.Resource, metric pmetric.Metric, settings Settings, - tsMap map[string]*prompb.TimeSeries) { +func addSingleSummaryDataPoint( + pt pmetric.SummaryDataPoint, + resource pcommon.Resource, + scope pcommon.InstrumentationScope, + metric pmetric.Metric, + settings Settings, + tsMap map[string]*prompb.TimeSeries, +) { timestamp := convertTimeStamp(pt.Timestamp()) // sum and count of the summary should append suffix to baseName baseName := prometheustranslator.BuildPromCompliantName(metric, settings.Namespace) @@ -451,7 +482,7 @@ func addSingleSummaryDataPoint(pt pmetric.SummaryDataPoint, resource pcommon.Res if pt.Flags().NoRecordedValue() { sum.Value = math.Float64frombits(value.StaleNaN) } - sumlabels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+sumStr) + sumlabels := createAttributes(resource, scope, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+sumStr) addSample(tsMap, sum, sumlabels, metric.Type().String()) // treat count as a sample in an individual TimeSeries @@ -462,7 +493,7 @@ func addSingleSummaryDataPoint(pt pmetric.SummaryDataPoint, resource pcommon.Res if pt.Flags().NoRecordedValue() { count.Value = math.Float64frombits(value.StaleNaN) } - countlabels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+countStr) + countlabels := createAttributes(resource, scope, pt.Attributes(), settings.ExternalLabels, nameStr, baseName+countStr) addSample(tsMap, count, countlabels, metric.Type().String()) // process each percentile/quantile @@ -476,7 +507,7 @@ func addSingleSummaryDataPoint(pt pmetric.SummaryDataPoint, resource pcommon.Res quantile.Value = math.Float64frombits(value.StaleNaN) } percentileStr := strconv.FormatFloat(qt.Quantile(), 'f', -1, 64) - qtlabels := createAttributes(resource, pt.Attributes(), settings.ExternalLabels, nameStr, baseName, quantileStr, percentileStr) + qtlabels := createAttributes(resource, scope, pt.Attributes(), settings.ExternalLabels, nameStr, baseName, quantileStr, percentileStr) addSample(tsMap, quantile, qtlabels, metric.Type().String()) } @@ -485,6 +516,7 @@ func addSingleSummaryDataPoint(pt pmetric.SummaryDataPoint, resource pcommon.Res if settings.ExportCreatedMetric && startTimestamp != 0 { createdLabels := createAttributes( resource, + scope, pt.Attributes(), settings.ExternalLabels, nameStr, @@ -542,7 +574,7 @@ func addResourceTargetInfo(resource pcommon.Resource, settings Settings, timesta if len(settings.Namespace) > 0 { name = settings.Namespace + "_" + name } - labels := createAttributes(resource, attributes, settings.ExternalLabels, nameStr, name) + labels := createAttributes(resource, pcommon.NewInstrumentationScope(), attributes, settings.ExternalLabels, nameStr, name) sample := &prompb.Sample{ Value: float64(1), // convert ns to ms @@ -551,6 +583,44 @@ func addResourceTargetInfo(resource pcommon.Resource, settings Settings, timesta addSample(tsMap, sample, labels, infoType) } +func addScopeTargetInfo( + scope pcommon.InstrumentationScope, + resource pcommon.Resource, + settings Settings, + timestamp pcommon.Timestamp, + tsMap map[string]*prompb.TimeSeries, +) { + if settings.DisableScopeInfo { + return + } + if scope.Attributes().Len() == 0 { + // If the scope doesn't have additional attributes, then otel_scope_info isn't useful. + return + } + + // Only add service name and instance id resource attributes + resCopy := pcommon.NewResource() + serviceName, ok := resource.Attributes().Get(conventions.AttributeServiceName) + if ok { + serviceName.CopyTo(resCopy.Attributes().PutEmpty(conventions.AttributeServiceName)) + } + serviceInstanceId, ok := resource.Attributes().Get(conventions.AttributeServiceInstanceID) + if ok { + serviceInstanceId.CopyTo(resCopy.Attributes().PutEmpty(conventions.AttributeServiceInstanceID)) + } + + name := scopeMetricName + if len(settings.Namespace) > 0 { + name = settings.Namespace + "_" + name + } + labels := createAttributes(resource, scope, scope.Attributes(), settings.ExternalLabels, nameStr, name) + sample := &prompb.Sample{ + Value: float64(1), + Timestamp: convertTimeStamp(timestamp), + } + addSample(tsMap, sample, labels, infoType) +} + // convertTimeStamp converts OTLP timestamp in ns to timestamp in ms func convertTimeStamp(timestamp pcommon.Timestamp) int64 { return timestamp.AsTime().UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond)) diff --git a/pkg/translator/prometheusremotewrite/helper_test.go b/pkg/translator/prometheusremotewrite/helper_test.go index ee9adea5a989..80282c5638cd 100644 --- a/pkg/translator/prometheusremotewrite/helper_test.go +++ b/pkg/translator/prometheusremotewrite/helper_test.go @@ -216,6 +216,7 @@ func Test_createLabelSet(t *testing.T) { tests := []struct { name string resource pcommon.Resource + scope pcommon.InstrumentationScope orig pcommon.Map externalLabels map[string]string extras []string @@ -224,6 +225,7 @@ func Test_createLabelSet(t *testing.T) { { "labels_clean", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs1, map[string]string{}, []string{label31, value31, label32, value32}, @@ -237,6 +239,7 @@ func Test_createLabelSet(t *testing.T) { res.Attributes().PutStr("service.instance.id", "127.0.0.1:8080") return res }(), + pcommon.NewInstrumentationScope(), lbs1, map[string]string{}, []string{label31, value31, label32, value32}, @@ -250,14 +253,57 @@ func Test_createLabelSet(t *testing.T) { res.Attributes().PutBool("service.instance.id", true) return res }(), + pcommon.NewInstrumentationScope(), lbs1, map[string]string{}, []string{label31, value31, label32, value32}, getPromLabels(label11, value11, label12, value12, label31, value31, label32, value32, "job", "12345", "instance", "true"), }, + { + "labels_with_scope", + pcommon.NewResource(), + func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.SetName("inst.scope.name") + scope.SetVersion("v1.2.3") + return scope + }(), + lbs1, + map[string]string{}, + []string{label31, value31, label32, value32}, + getPromLabels(label11, value11, label12, value12, label31, value31, label32, value32, "otel_scope_name", "inst.scope.name", "otel_scope_version", "v1.2.3"), + }, + { + "labels_with_empty_scope", + pcommon.NewResource(), + func() pcommon.InstrumentationScope { + return pcommon.NewInstrumentationScope() + }(), + lbs1, + map[string]string{}, + []string{label31, value31, label32, value32}, + getPromLabels(label11, value11, label12, value12, label31, value31, label32, value32), + }, + { + "labels_with_scope_attributes", + pcommon.NewResource(), + func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.SetName("inst.scope.name") + scope.Attributes().PutStr("foo", "bar") + scope.Attributes().PutInt("num", 555) + scope.SetVersion("v1.2.3") + return scope + }(), + lbs1, + map[string]string{}, + []string{label31, value31, label32, value32}, + getPromLabels(label11, value11, label12, value12, label31, value31, label32, value32, "otel_scope_name", "inst.scope.name", "otel_scope_version", "v1.2.3"), + }, { "labels_duplicate_in_extras", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs1, map[string]string{}, []string{label11, value31}, @@ -266,6 +312,7 @@ func Test_createLabelSet(t *testing.T) { { "labels_dirty", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs1Dirty, map[string]string{}, []string{label31 + dirty1, value31, label32, value32}, @@ -274,6 +321,7 @@ func Test_createLabelSet(t *testing.T) { { "no_original_case", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), pcommon.NewMap(), nil, []string{label31, value31, label32, value32}, @@ -282,6 +330,7 @@ func Test_createLabelSet(t *testing.T) { { "empty_extra_case", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs1, map[string]string{}, []string{"", ""}, @@ -290,6 +339,7 @@ func Test_createLabelSet(t *testing.T) { { "single_left_over_case", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs1, map[string]string{}, []string{label31, value31, label32}, @@ -298,6 +348,7 @@ func Test_createLabelSet(t *testing.T) { { "valid_external_labels", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs1, exlbs1, []string{label31, value31, label32, value32}, @@ -306,6 +357,7 @@ func Test_createLabelSet(t *testing.T) { { "overwritten_external_labels", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs1, exlbs2, []string{label31, value31, label32, value32}, @@ -314,6 +366,7 @@ func Test_createLabelSet(t *testing.T) { { "colliding attributes", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbsColliding, nil, []string{label31, value31, label32, value32}, @@ -322,6 +375,7 @@ func Test_createLabelSet(t *testing.T) { { "sanitize_labels_starts_with_underscore", pcommon.NewResource(), + pcommon.NewInstrumentationScope(), lbs3, exlbs1, []string{label31, value31, label32, value32}, @@ -331,13 +385,14 @@ func Test_createLabelSet(t *testing.T) { // run tests for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.ElementsMatch(t, tt.want, createAttributes(tt.resource, tt.orig, tt.externalLabels, tt.extras...)) + assert.ElementsMatch(t, tt.want, createAttributes(tt.resource, tt.scope, tt.orig, tt.externalLabels, tt.extras...)) }) } } func BenchmarkCreateAttributes(b *testing.B) { r := pcommon.NewResource() + s := pcommon.NewInstrumentationScope() ext := map[string]string{} m := pcommon.NewMap() @@ -349,7 +404,7 @@ func BenchmarkCreateAttributes(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - createAttributes(r, m, ext) + createAttributes(r, s, m, ext) } } @@ -631,6 +686,116 @@ func TestAddResourceTargetInfo(t *testing.T) { } } +func TestAddScopeTargetInfo(t *testing.T) { + for _, tc := range []struct { + desc string + resource pcommon.Resource + scope pcommon.InstrumentationScope + settings Settings + timestamp pcommon.Timestamp + expected map[string]*prompb.TimeSeries + }{ + { + "disable scope info metric", + pcommon.NewResource(), + pcommon.NewInstrumentationScope(), + Settings{DisableScopeInfo: true}, + testdata.TestMetricStartTimestamp, + map[string]*prompb.TimeSeries{}, + }, + { + "empty scope attributes", + pcommon.NewResource(), + pcommon.NewInstrumentationScope(), + Settings{}, + testdata.TestMetricStartTimestamp, + map[string]*prompb.TimeSeries{}, + }, + { + "with scope attributes", + func() pcommon.Resource { + res := pcommon.NewResource() + res.Attributes().PutStr("service.name", "prometheus") + res.Attributes().PutStr("service.instance.id", "127.0.0.1:8080") + res.Attributes().PutStr("res.foo", "res.bar") + return res + }(), + func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.Attributes().PutStr("foo", "bar") + return scope + }(), + Settings{}, + testdata.TestMetricStartTimestamp, + map[string]*prompb.TimeSeries{ + "info-__name__-otel_scope_info-foo-bar-instance-127.0.0.1:8080-job-prometheus": { + Labels: []prompb.Label{ + { + Name: "__name__", + Value: "otel_scope_info", + }, + { + Name: "foo", + Value: "bar", + }, + { + Name: "instance", + Value: "127.0.0.1:8080", + }, + { + Name: "job", + Value: "prometheus", + }, + }, + Samples: []prompb.Sample{ + { + Value: 1, + Timestamp: 1581452772000, + }, + }, + }, + }, + }, + { + "with namespace and scope attributes", + pcommon.NewResource(), + func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.Attributes().PutStr("foo", "bar") + return scope + }(), + Settings{Namespace: "foo"}, + testdata.TestMetricStartTimestamp, + map[string]*prompb.TimeSeries{ + "info-__name__-foo_otel_scope_info-foo-bar": { + Labels: []prompb.Label{ + { + Name: "__name__", + Value: "foo_otel_scope_info", + }, + { + Name: "foo", + Value: "bar", + }, + }, + Samples: []prompb.Sample{ + { + Value: 1, + Timestamp: 1581452772000, + }, + }, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + tsMap := map[string]*prompb.TimeSeries{} + addScopeTargetInfo(tc.scope, tc.resource, tc.settings, tc.timestamp, tsMap) + assert.Exactly(t, tc.expected, tsMap) + }) + } +} + func TestMostRecentTimestampInMetric(t *testing.T) { laterTimestamp := pcommon.NewTimestampFromTime(testdata.TestMetricTime.Add(1 * time.Minute)) metricMultipleTimestamps := testdata.GenerateMetricsOneMetric().ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0) @@ -756,6 +921,7 @@ func TestAddSingleSummaryDataPoint(t *testing.T) { addSingleSummaryDataPoint( metric.Summary().DataPoints().At(x), pcommon.NewResource(), + pcommon.NewInstrumentationScope(), metric, Settings{ ExportCreatedMetric: true, @@ -867,6 +1033,7 @@ func TestAddSingleHistogramDataPoint(t *testing.T) { addSingleHistogramDataPoint( metric.Histogram().DataPoints().At(x), pcommon.NewResource(), + pcommon.NewInstrumentationScope(), metric, Settings{ ExportCreatedMetric: true, diff --git a/pkg/translator/prometheusremotewrite/histograms.go b/pkg/translator/prometheusremotewrite/histograms.go index 293d318a3c58..9d529090d2ba 100644 --- a/pkg/translator/prometheusremotewrite/histograms.go +++ b/pkg/translator/prometheusremotewrite/histograms.go @@ -20,11 +20,13 @@ func addSingleExponentialHistogramDataPoint( metric string, pt pmetric.ExponentialHistogramDataPoint, resource pcommon.Resource, + scope pcommon.InstrumentationScope, settings Settings, series map[string]*prompb.TimeSeries, ) error { labels := createAttributes( resource, + scope, pt.Attributes(), settings.ExternalLabels, model.MetricNameLabel, metric, diff --git a/pkg/translator/prometheusremotewrite/histograms_test.go b/pkg/translator/prometheusremotewrite/histograms_test.go index a5b9f47194eb..c0bd6feb7f3a 100644 --- a/pkg/translator/prometheusremotewrite/histograms_test.go +++ b/pkg/translator/prometheusremotewrite/histograms_test.go @@ -375,6 +375,7 @@ func TestAddSingleExponentialHistogramDataPoint(t *testing.T) { prometheustranslator.BuildPromCompliantName(metric, ""), metric.ExponentialHistogram().DataPoints().At(x), pcommon.NewResource(), + pcommon.NewInstrumentationScope(), Settings{}, gotSeries, ) diff --git a/pkg/translator/prometheusremotewrite/metrics_to_prw.go b/pkg/translator/prometheusremotewrite/metrics_to_prw.go index 205e279020f4..6dbc8bd15ee3 100644 --- a/pkg/translator/prometheusremotewrite/metrics_to_prw.go +++ b/pkg/translator/prometheusremotewrite/metrics_to_prw.go @@ -19,6 +19,7 @@ type Settings struct { Namespace string ExternalLabels map[string]string DisableTargetInfo bool + DisableScopeInfo bool ExportCreatedMetric bool } @@ -36,6 +37,7 @@ func FromMetrics(md pmetric.Metrics, settings Settings) (tsMap map[string]*promp var mostRecentTimestamp pcommon.Timestamp for j := 0; j < scopeMetricsSlice.Len(); j++ { scopeMetrics := scopeMetricsSlice.At(j) + scope := scopeMetrics.Scope() metricSlice := scopeMetrics.Metrics() // TODO: decide if instrumentation library information should be exported as labels @@ -56,7 +58,7 @@ func FromMetrics(md pmetric.Metrics, settings Settings) (tsMap map[string]*promp errs = multierr.Append(errs, fmt.Errorf("empty data points. %s is dropped", metric.Name())) } for x := 0; x < dataPoints.Len(); x++ { - addSingleGaugeNumberDataPoint(dataPoints.At(x), resource, metric, settings, tsMap) + addSingleGaugeNumberDataPoint(dataPoints.At(x), resource, scope, metric, settings, tsMap) } case pmetric.MetricTypeSum: dataPoints := metric.Sum().DataPoints() @@ -64,7 +66,7 @@ func FromMetrics(md pmetric.Metrics, settings Settings) (tsMap map[string]*promp errs = multierr.Append(errs, fmt.Errorf("empty data points. %s is dropped", metric.Name())) } for x := 0; x < dataPoints.Len(); x++ { - addSingleSumNumberDataPoint(dataPoints.At(x), resource, metric, settings, tsMap) + addSingleSumNumberDataPoint(dataPoints.At(x), resource, scope, metric, settings, tsMap) } case pmetric.MetricTypeHistogram: dataPoints := metric.Histogram().DataPoints() @@ -72,7 +74,7 @@ func FromMetrics(md pmetric.Metrics, settings Settings) (tsMap map[string]*promp errs = multierr.Append(errs, fmt.Errorf("empty data points. %s is dropped", metric.Name())) } for x := 0; x < dataPoints.Len(); x++ { - addSingleHistogramDataPoint(dataPoints.At(x), resource, metric, settings, tsMap) + addSingleHistogramDataPoint(dataPoints.At(x), resource, scope, metric, settings, tsMap) } case pmetric.MetricTypeExponentialHistogram: dataPoints := metric.ExponentialHistogram().DataPoints() @@ -87,6 +89,7 @@ func FromMetrics(md pmetric.Metrics, settings Settings) (tsMap map[string]*promp name, dataPoints.At(x), resource, + scope, settings, tsMap, ), @@ -98,12 +101,13 @@ func FromMetrics(md pmetric.Metrics, settings Settings) (tsMap map[string]*promp errs = multierr.Append(errs, fmt.Errorf("empty data points. %s is dropped", metric.Name())) } for x := 0; x < dataPoints.Len(); x++ { - addSingleSummaryDataPoint(dataPoints.At(x), resource, metric, settings, tsMap) + addSingleSummaryDataPoint(dataPoints.At(x), resource, scope, metric, settings, tsMap) } default: errs = multierr.Append(errs, errors.New("unsupported metric type")) } } + addScopeTargetInfo(scope, resource, settings, mostRecentTimestamp, tsMap) } addResourceTargetInfo(resource, settings, mostRecentTimestamp, tsMap) } diff --git a/pkg/translator/prometheusremotewrite/number_data_points.go b/pkg/translator/prometheusremotewrite/number_data_points.go index d50ed6526513..51c00f58f989 100644 --- a/pkg/translator/prometheusremotewrite/number_data_points.go +++ b/pkg/translator/prometheusremotewrite/number_data_points.go @@ -21,6 +21,7 @@ import ( func addSingleGaugeNumberDataPoint( pt pmetric.NumberDataPoint, resource pcommon.Resource, + scope pcommon.InstrumentationScope, metric pmetric.Metric, settings Settings, series map[string]*prompb.TimeSeries, @@ -28,6 +29,7 @@ func addSingleGaugeNumberDataPoint( name := prometheustranslator.BuildPromCompliantName(metric, settings.Namespace) labels := createAttributes( resource, + scope, pt.Attributes(), settings.ExternalLabels, model.MetricNameLabel, name, @@ -54,6 +56,7 @@ func addSingleGaugeNumberDataPoint( func addSingleSumNumberDataPoint( pt pmetric.NumberDataPoint, resource pcommon.Resource, + scope pcommon.InstrumentationScope, metric pmetric.Metric, settings Settings, series map[string]*prompb.TimeSeries, @@ -61,6 +64,7 @@ func addSingleSumNumberDataPoint( name := prometheustranslator.BuildPromCompliantName(metric, settings.Namespace) labels := createAttributes( resource, + scope, pt.Attributes(), settings.ExternalLabels, model.MetricNameLabel, name, @@ -91,6 +95,7 @@ func addSingleSumNumberDataPoint( if startTimestamp != 0 { createdLabels := createAttributes( resource, + scope, pt.Attributes(), settings.ExternalLabels, nameStr, diff --git a/pkg/translator/prometheusremotewrite/number_data_points_test.go b/pkg/translator/prometheusremotewrite/number_data_points_test.go index 39b13fcd3d9d..30198a67597d 100644 --- a/pkg/translator/prometheusremotewrite/number_data_points_test.go +++ b/pkg/translator/prometheusremotewrite/number_data_points_test.go @@ -57,6 +57,7 @@ func TestAddSingleGaugeNumberDataPoint(t *testing.T) { addSingleGaugeNumberDataPoint( metric.Gauge().DataPoints().At(x), pcommon.NewResource(), + pcommon.NewInstrumentationScope(), metric, Settings{}, gotSeries, @@ -233,6 +234,7 @@ func TestAddSingleSumNumberDataPoint(t *testing.T) { addSingleSumNumberDataPoint( metric.Sum().DataPoints().At(x), pcommon.NewResource(), + pcommon.NewInstrumentationScope(), metric, Settings{ExportCreatedMetric: true}, got, From c0c0acd320e089497459b8b32bda01d822ada66b Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Mon, 17 Jul 2023 12:37:14 -0600 Subject: [PATCH 2/8] default otel_scope_info metric generation to false for prometheus remote write exporter --- .../prometheusremotewriteexporter/README.md | 2 +- .../prometheusremotewriteexporter/factory.go | 2 +- .../prometheusremotewrite/helper_test.go | 26 +++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/exporter/prometheusremotewriteexporter/README.md b/exporter/prometheusremotewriteexporter/README.md index e8dfcc4b3138..d6474fb2a49d 100644 --- a/exporter/prometheusremotewriteexporter/README.md +++ b/exporter/prometheusremotewriteexporter/README.md @@ -59,7 +59,7 @@ The following settings can be optionally configured: - `target_info`: customize `target_info` metric - `enabled` (default = true): If `enabled` is `true`, a `target_info` metric will be generated for each resource metric (see https://github.com/open-telemetry/opentelemetry-specification/pull/2381). - `scope_info`: customize `otel_scope_info` metric - - `enabled` (default = true): If `enabled` is `true`, a `otel_scope_info` metric will be generated for each instrumentation scope metric (see https://github.com/open-telemetry/opentelemetry-specification/pull/2703). + - `enabled` (default = false): If `enabled` is `true`, a `otel_scope_info` metric will be generated for each instrumentation scope metric (see https://github.com/open-telemetry/opentelemetry-specification/pull/2703). - `export_created_metric`: - `enabled` (default = false): If `enabled` is `true`, a `_created` metric is exported for Summary, Histogram, and Monotonic Sum metric points if diff --git a/exporter/prometheusremotewriteexporter/factory.go b/exporter/prometheusremotewriteexporter/factory.go index d7f87cfc6693..cdad77d1aeb2 100644 --- a/exporter/prometheusremotewriteexporter/factory.go +++ b/exporter/prometheusremotewriteexporter/factory.go @@ -98,7 +98,7 @@ func createDefaultConfig() component.Config { Enabled: true, }, ScopeInfo: &ScopeInfo{ - Enabled: true, + Enabled: false, }, CreatedMetric: &CreatedMetric{ Enabled: false, diff --git a/pkg/translator/prometheusremotewrite/helper_test.go b/pkg/translator/prometheusremotewrite/helper_test.go index 80282c5638cd..9aa5d51b4682 100644 --- a/pkg/translator/prometheusremotewrite/helper_test.go +++ b/pkg/translator/prometheusremotewrite/helper_test.go @@ -273,6 +273,32 @@ func Test_createLabelSet(t *testing.T) { []string{label31, value31, label32, value32}, getPromLabels(label11, value11, label12, value12, label31, value31, label32, value32, "otel_scope_name", "inst.scope.name", "otel_scope_version", "v1.2.3"), }, + { + "labels_with_scope_name_and_no_version", + pcommon.NewResource(), + func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.SetName("inst.scope.name") + return scope + }(), + lbs1, + map[string]string{}, + []string{label31, value31, label32, value32}, + getPromLabels(label11, value11, label12, value12, label31, value31, label32, value32, "otel_scope_name", "inst.scope.name"), + }, + { + "labels_with_scope_version_and_no_name", + pcommon.NewResource(), + func() pcommon.InstrumentationScope { + scope := pcommon.NewInstrumentationScope() + scope.SetVersion("v1.2.3") + return scope + }(), + lbs1, + map[string]string{}, + []string{label31, value31, label32, value32}, + getPromLabels(label11, value11, label12, value12, label31, value31, label32, value32, "otel_scope_version", "v1.2.3"), + }, { "labels_with_empty_scope", pcommon.NewResource(), From b7a328bf165cf601b91bba45df686d6185aebdba Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Mon, 24 Jul 2023 14:56:35 -0600 Subject: [PATCH 3/8] fix lints and tests --- exporter/prometheusremotewriteexporter/config_test.go | 3 +++ exporter/prometheusremotewriteexporter/exporter_test.go | 9 +++++++++ pkg/translator/prometheusremotewrite/helper.go | 4 ++-- pkg/translator/prometheusremotewrite/helper_test.go | 4 +--- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/exporter/prometheusremotewriteexporter/config_test.go b/exporter/prometheusremotewriteexporter/config_test.go index 2dcee0eeac49..804108391a05 100644 --- a/exporter/prometheusremotewriteexporter/config_test.go +++ b/exporter/prometheusremotewriteexporter/config_test.go @@ -76,6 +76,9 @@ func TestLoadConfig(t *testing.T) { TargetInfo: &TargetInfo{ Enabled: true, }, + ScopeInfo: &ScopeInfo{ + Enabled: false, + }, CreatedMetric: &CreatedMetric{Enabled: true}, }, }, diff --git a/exporter/prometheusremotewriteexporter/exporter_test.go b/exporter/prometheusremotewriteexporter/exporter_test.go index 35ff6028e427..dc86b4811187 100644 --- a/exporter/prometheusremotewriteexporter/exporter_test.go +++ b/exporter/prometheusremotewriteexporter/exporter_test.go @@ -41,6 +41,9 @@ func Test_NewPRWExporter(t *testing.T) { TargetInfo: &TargetInfo{ Enabled: true, }, + ScopeInfo: &ScopeInfo{ + Enabled: false, + }, CreatedMetric: &CreatedMetric{ Enabled: false, }, @@ -136,6 +139,9 @@ func Test_Start(t *testing.T) { TargetInfo: &TargetInfo{ Enabled: true, }, + ScopeInfo: &ScopeInfo{ + Enabled: false, + }, CreatedMetric: &CreatedMetric{ Enabled: false, }, @@ -679,6 +685,9 @@ func Test_PushMetrics(t *testing.T) { TargetInfo: &TargetInfo{ Enabled: true, }, + ScopeInfo: &ScopeInfo{ + Enabled: false, + }, CreatedMetric: &CreatedMetric{ Enabled: true, }, diff --git a/pkg/translator/prometheusremotewrite/helper.go b/pkg/translator/prometheusremotewrite/helper.go index 6ab7ec744079..ac0b8618966b 100644 --- a/pkg/translator/prometheusremotewrite/helper.go +++ b/pkg/translator/prometheusremotewrite/helper.go @@ -604,9 +604,9 @@ func addScopeTargetInfo( if ok { serviceName.CopyTo(resCopy.Attributes().PutEmpty(conventions.AttributeServiceName)) } - serviceInstanceId, ok := resource.Attributes().Get(conventions.AttributeServiceInstanceID) + serviceInstanceID, ok := resource.Attributes().Get(conventions.AttributeServiceInstanceID) if ok { - serviceInstanceId.CopyTo(resCopy.Attributes().PutEmpty(conventions.AttributeServiceInstanceID)) + serviceInstanceID.CopyTo(resCopy.Attributes().PutEmpty(conventions.AttributeServiceInstanceID)) } name := scopeMetricName diff --git a/pkg/translator/prometheusremotewrite/helper_test.go b/pkg/translator/prometheusremotewrite/helper_test.go index 9aa5d51b4682..dfd633f0d384 100644 --- a/pkg/translator/prometheusremotewrite/helper_test.go +++ b/pkg/translator/prometheusremotewrite/helper_test.go @@ -302,9 +302,7 @@ func Test_createLabelSet(t *testing.T) { { "labels_with_empty_scope", pcommon.NewResource(), - func() pcommon.InstrumentationScope { - return pcommon.NewInstrumentationScope() - }(), + pcommon.NewInstrumentationScope(), lbs1, map[string]string{}, []string{label31, value31, label32, value32}, From dabcd5dd55b8508e633853aab358b136cf396bb5 Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Tue, 1 Aug 2023 11:20:28 -0600 Subject: [PATCH 4/8] add changelog entry --- .chloggen/O11Y-3152.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 .chloggen/O11Y-3152.yaml diff --git a/.chloggen/O11Y-3152.yaml b/.chloggen/O11Y-3152.yaml new file mode 100755 index 000000000000..7c3396d39bfd --- /dev/null +++ b/.chloggen/O11Y-3152.yaml @@ -0,0 +1,20 @@ +# 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: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: prometheusremotewriteexporter + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add otel_scope_info metric to prometheus remote write exporter. + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [21091] + +# (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: From 3f146d90bd9c622c33359c71fcae89162a263f2c Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Mon, 14 Aug 2023 11:37:26 -0600 Subject: [PATCH 5/8] emit otel_scope_info metric when scope doesn't contain attributes --- .chloggen/O11Y-3152.yaml | 2 +- .../prometheusremotewrite/helper.go | 8 ++----- .../prometheusremotewrite/helper_test.go | 21 ++++++++++++++++--- .../prometheusremotewrite/metrics_to_prw.go | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/.chloggen/O11Y-3152.yaml b/.chloggen/O11Y-3152.yaml index 7c3396d39bfd..53e3f2e06c65 100755 --- a/.chloggen/O11Y-3152.yaml +++ b/.chloggen/O11Y-3152.yaml @@ -9,7 +9,7 @@ change_type: enhancement component: prometheusremotewriteexporter # A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). -note: Add otel_scope_info metric to prometheus remote write exporter. +note: Emit `otel_scope_info` metric, and add `otel_scope_name` and `otel_scope_version` labels to metrics. # Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. issues: [21091] diff --git a/pkg/translator/prometheusremotewrite/helper.go b/pkg/translator/prometheusremotewrite/helper.go index 0ca87cd93782..ab49a8849b03 100644 --- a/pkg/translator/prometheusremotewrite/helper.go +++ b/pkg/translator/prometheusremotewrite/helper.go @@ -604,9 +604,9 @@ func addResourceTargetInfo(resource pcommon.Resource, settings Settings, timesta addSample(tsMap, sample, labels, infoType) } -func addScopeTargetInfo( - scope pcommon.InstrumentationScope, +func addScopeInfo( resource pcommon.Resource, + scope pcommon.InstrumentationScope, settings Settings, timestamp pcommon.Timestamp, tsMap map[string]*prompb.TimeSeries, @@ -614,10 +614,6 @@ func addScopeTargetInfo( if settings.DisableScopeInfo { return } - if scope.Attributes().Len() == 0 { - // If the scope doesn't have additional attributes, then otel_scope_info isn't useful. - return - } // Only add service name and instance id resource attributes resCopy := pcommon.NewResource() diff --git a/pkg/translator/prometheusremotewrite/helper_test.go b/pkg/translator/prometheusremotewrite/helper_test.go index dfd633f0d384..393570e8a722 100644 --- a/pkg/translator/prometheusremotewrite/helper_test.go +++ b/pkg/translator/prometheusremotewrite/helper_test.go @@ -710,7 +710,7 @@ func TestAddResourceTargetInfo(t *testing.T) { } } -func TestAddScopeTargetInfo(t *testing.T) { +func TestAddScopeInfo(t *testing.T) { for _, tc := range []struct { desc string resource pcommon.Resource @@ -733,7 +733,22 @@ func TestAddScopeTargetInfo(t *testing.T) { pcommon.NewInstrumentationScope(), Settings{}, testdata.TestMetricStartTimestamp, - map[string]*prompb.TimeSeries{}, + map[string]*prompb.TimeSeries{ + "info-__name__-otel_scope_info": { + Labels: []prompb.Label{ + { + Name: "__name__", + Value: "otel_scope_info", + }, + }, + Samples: []prompb.Sample{ + { + Value: 1, + Timestamp: 1581452772000, + }, + }, + }, + }, }, { "with scope attributes", @@ -814,7 +829,7 @@ func TestAddScopeTargetInfo(t *testing.T) { } { t.Run(tc.desc, func(t *testing.T) { tsMap := map[string]*prompb.TimeSeries{} - addScopeTargetInfo(tc.scope, tc.resource, tc.settings, tc.timestamp, tsMap) + addScopeInfo(tc.resource, tc.scope, tc.settings, tc.timestamp, tsMap) assert.Exactly(t, tc.expected, tsMap) }) } diff --git a/pkg/translator/prometheusremotewrite/metrics_to_prw.go b/pkg/translator/prometheusremotewrite/metrics_to_prw.go index 52d4afea9296..199fb280ec06 100644 --- a/pkg/translator/prometheusremotewrite/metrics_to_prw.go +++ b/pkg/translator/prometheusremotewrite/metrics_to_prw.go @@ -108,7 +108,7 @@ func FromMetrics(md pmetric.Metrics, settings Settings) (tsMap map[string]*promp errs = multierr.Append(errs, errors.New("unsupported metric type")) } } - addScopeTargetInfo(scope, resource, settings, mostRecentTimestamp, tsMap) + addScopeInfo(resource, scope, settings, mostRecentTimestamp, tsMap) } addResourceTargetInfo(resource, settings, mostRecentTimestamp, tsMap) } From 9cef3ce218f3b1d03487b3bf4c4182a1ffdd77fe Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Fri, 13 Oct 2023 11:15:11 -0600 Subject: [PATCH 6/8] drop otel_scope_info metric when scope attributes are empty --- pkg/translator/prometheusremotewrite/helper.go | 4 ++++ .../prometheusremotewrite/helper_test.go | 17 +---------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/pkg/translator/prometheusremotewrite/helper.go b/pkg/translator/prometheusremotewrite/helper.go index 74c42d4b0967..cf673bfa5dcc 100644 --- a/pkg/translator/prometheusremotewrite/helper.go +++ b/pkg/translator/prometheusremotewrite/helper.go @@ -616,6 +616,10 @@ func addScopeInfo( if settings.DisableScopeInfo { return } + if scope.Attributes().Len() == 0 { + // If the scope doesn't have additional attributes, then otel_scope_info isn't useful. + return + } // Only add service name and instance id resource attributes resCopy := pcommon.NewResource() diff --git a/pkg/translator/prometheusremotewrite/helper_test.go b/pkg/translator/prometheusremotewrite/helper_test.go index 393570e8a722..495082b86bd7 100644 --- a/pkg/translator/prometheusremotewrite/helper_test.go +++ b/pkg/translator/prometheusremotewrite/helper_test.go @@ -733,22 +733,7 @@ func TestAddScopeInfo(t *testing.T) { pcommon.NewInstrumentationScope(), Settings{}, testdata.TestMetricStartTimestamp, - map[string]*prompb.TimeSeries{ - "info-__name__-otel_scope_info": { - Labels: []prompb.Label{ - { - Name: "__name__", - Value: "otel_scope_info", - }, - }, - Samples: []prompb.Sample{ - { - Value: 1, - Timestamp: 1581452772000, - }, - }, - }, - }, + map[string]*prompb.TimeSeries{}, }, { "with scope attributes", From a50c3ef5de70c3337c3c4a0753e19e3043722cef Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Mon, 16 Oct 2023 16:04:18 -0600 Subject: [PATCH 7/8] remove unnecessary resource copy --- .../prometheusremotewrite/helper.go | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/pkg/translator/prometheusremotewrite/helper.go b/pkg/translator/prometheusremotewrite/helper.go index cf673bfa5dcc..373c50cdf36a 100644 --- a/pkg/translator/prometheusremotewrite/helper.go +++ b/pkg/translator/prometheusremotewrite/helper.go @@ -168,6 +168,9 @@ func createAttributes( serviceName, haveServiceName := resource.Attributes().Get(conventions.AttributeServiceName) instance, haveInstanceID := resource.Attributes().Get(conventions.AttributeServiceInstanceID) + scopeName := scope.Name() + scopeVersion := scope.Version() + // Calculate the maximum possible number of labels we could return so we can preallocate l maxLabelCount := attributes.Len() + len(externalLabels) + len(extras)/2 @@ -179,6 +182,14 @@ func createAttributes( maxLabelCount++ } + if len(scopeName) > 0 { + maxLabelCount++ + } + + if len(scopeVersion) > 0 { + maxLabelCount++ + } + // map ensures no duplicate label name l := make(map[string]string, maxLabelCount) @@ -212,6 +223,13 @@ func createAttributes( if haveInstanceID { l[model.InstanceLabel] = instance.AsString() } + // add scope name/version labels + if len(scopeName) > 0 { + l[scopeAttrName] = scopeName + } + if len(scopeVersion) > 0 { + l[scopeAttrVersion] = scopeVersion + } for key, value := range externalLabels { // External labels have already been sanitized if _, alreadyExists := l[key]; alreadyExists { @@ -221,14 +239,6 @@ func createAttributes( l[key] = value } - // add scope name/version labels - if len(scope.Name()) > 0 { - extras = append(extras, scopeAttrName, scope.Name()) - } - if len(scope.Version()) > 0 { - extras = append(extras, scopeAttrVersion, scope.Version()) - } - for i := 0; i < len(extras); i += 2 { if i+1 >= len(extras) { break @@ -621,17 +631,6 @@ func addScopeInfo( return } - // Only add service name and instance id resource attributes - resCopy := pcommon.NewResource() - serviceName, ok := resource.Attributes().Get(conventions.AttributeServiceName) - if ok { - serviceName.CopyTo(resCopy.Attributes().PutEmpty(conventions.AttributeServiceName)) - } - serviceInstanceID, ok := resource.Attributes().Get(conventions.AttributeServiceInstanceID) - if ok { - serviceInstanceID.CopyTo(resCopy.Attributes().PutEmpty(conventions.AttributeServiceInstanceID)) - } - name := scopeMetricName if len(settings.Namespace) > 0 { name = settings.Namespace + "_" + name From d47d532203e709af1016b829e5fe211d389a26bd Mon Sep 17 00:00:00 2001 From: blakeroberts-wk Date: Wed, 18 Oct 2023 10:22:51 -0600 Subject: [PATCH 8/8] add scope name/version to prometheus remote write helpers unit test --- pkg/translator/prometheusremotewrite/helper_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/translator/prometheusremotewrite/helper_test.go b/pkg/translator/prometheusremotewrite/helper_test.go index 495082b86bd7..d65af5eaa607 100644 --- a/pkg/translator/prometheusremotewrite/helper_test.go +++ b/pkg/translator/prometheusremotewrite/helper_test.go @@ -746,13 +746,15 @@ func TestAddScopeInfo(t *testing.T) { }(), func() pcommon.InstrumentationScope { scope := pcommon.NewInstrumentationScope() + scope.SetName("scope_name_foo") + scope.SetVersion("scope_version_bar") scope.Attributes().PutStr("foo", "bar") return scope }(), Settings{}, testdata.TestMetricStartTimestamp, map[string]*prompb.TimeSeries{ - "info-__name__-otel_scope_info-foo-bar-instance-127.0.0.1:8080-job-prometheus": { + "info-__name__-otel_scope_info-foo-bar-instance-127.0.0.1:8080-job-prometheus-otel_scope_name-scope_name_foo-otel_scope_version-scope_version_bar": { Labels: []prompb.Label{ { Name: "__name__", @@ -770,6 +772,14 @@ func TestAddScopeInfo(t *testing.T) { Name: "job", Value: "prometheus", }, + { + Name: "otel_scope_name", + Value: "scope_name_foo", + }, + { + Name: "otel_scope_version", + Value: "scope_version_bar", + }, }, Samples: []prompb.Sample{ {