From 6a8c88d68fc214d54f374ad6d0025fd14fcba2c4 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 4 Oct 2024 11:04:25 -0700 Subject: [PATCH] [chore] Improve otel metrics performance, pre-calculate attribute Set (#11288) Depends on https://github.com/open-telemetry/opentelemetry-collector/pull/11293 Signed-off-by: Bogdan Drutu --- .../exporterhelper/internal/obsexporter.go | 18 ++++++++---------- processor/processorhelper/obsreport.go | 14 ++++++++------ receiver/receiverhelper/obsreport.go | 10 +++++----- receiver/scraperhelper/obsreport.go | 10 +++++----- service/telemetry/internal/otelinit/config.go | 15 +++++++-------- service/telemetry/metrics_test.go | 4 ++-- 6 files changed, 35 insertions(+), 36 deletions(-) diff --git a/exporter/exporterhelper/internal/obsexporter.go b/exporter/exporterhelper/internal/obsexporter.go index 0805c5ac542..d6c3d841be3 100644 --- a/exporter/exporterhelper/internal/obsexporter.go +++ b/exporter/exporterhelper/internal/obsexporter.go @@ -23,7 +23,7 @@ type ObsReport struct { tracer trace.Tracer Signal pipeline.Signal - otelAttrs []attribute.KeyValue + otelAttrs attribute.Set TelemetryBuilder *metadata.TelemetryBuilder } @@ -41,12 +41,10 @@ func NewExporter(cfg ObsReportSettings) (*ObsReport, error) { } return &ObsReport{ - spanNamePrefix: ExporterPrefix + cfg.ExporterID.String(), - tracer: cfg.ExporterCreateSettings.TracerProvider.Tracer(cfg.ExporterID.String()), - Signal: cfg.Signal, - otelAttrs: []attribute.KeyValue{ - attribute.String(ExporterKey, cfg.ExporterID.String()), - }, + spanNamePrefix: ExporterPrefix + cfg.ExporterID.String(), + tracer: cfg.ExporterCreateSettings.TracerProvider.Tracer(cfg.ExporterID.String()), + Signal: cfg.Signal, + otelAttrs: attribute.NewSet(attribute.String(ExporterKey, cfg.ExporterID.String())), TelemetryBuilder: telemetryBuilder, }, nil } @@ -118,8 +116,8 @@ func (or *ObsReport) recordMetrics(ctx context.Context, signal pipeline.Signal, failedMeasure = or.TelemetryBuilder.ExporterSendFailedLogRecords } - sentMeasure.Add(ctx, sent, metric.WithAttributes(or.otelAttrs...)) - failedMeasure.Add(ctx, failed, metric.WithAttributes(or.otelAttrs...)) + sentMeasure.Add(ctx, sent, metric.WithAttributeSet(or.otelAttrs)) + failedMeasure.Add(ctx, failed, metric.WithAttributeSet(or.otelAttrs)) } func endSpan(ctx context.Context, err error, numSent, numFailedToSend int64, sentItemsKey, failedToSendItemsKey string) { @@ -155,5 +153,5 @@ func (or *ObsReport) RecordEnqueueFailure(ctx context.Context, signal pipeline.S enqueueFailedMeasure = or.TelemetryBuilder.ExporterEnqueueFailedLogRecords } - enqueueFailedMeasure.Add(ctx, failed, metric.WithAttributes(or.otelAttrs...)) + enqueueFailedMeasure.Add(ctx, failed, metric.WithAttributeSet(or.otelAttrs)) } diff --git a/processor/processorhelper/obsreport.go b/processor/processorhelper/obsreport.go index fd95f51fb9d..7bee8e086b2 100644 --- a/processor/processorhelper/obsreport.go +++ b/processor/processorhelper/obsreport.go @@ -17,6 +17,8 @@ import ( "go.opentelemetry.io/collector/processor/processorhelper/internal/metadata" ) +const signalKey = "otel.signal" + // Deprecated: [v0.111.0] no longer needed. To be removed in future. func BuildCustomMetricName(configType, metric string) string { componentPrefix := internal.ProcessorMetricPrefix @@ -44,7 +46,7 @@ func NewObsReport(_ ObsReportSettings) (*ObsReport, error) { } type obsReport struct { - otelAttrs []attribute.KeyValue + otelAttrs attribute.Set telemetryBuilder *metadata.TelemetryBuilder } @@ -54,15 +56,15 @@ func newObsReport(set processor.Settings, signal pipeline.Signal) (*obsReport, e return nil, err } return &obsReport{ - otelAttrs: []attribute.KeyValue{ + otelAttrs: attribute.NewSet( attribute.String(internal.ProcessorKey, set.ID.String()), - attribute.String("otel.signal", signal.String()), - }, + attribute.String(signalKey, signal.String()), + ), telemetryBuilder: telemetryBuilder, }, nil } func (or *obsReport) recordInOut(ctx context.Context, incoming, outgoing int) { - or.telemetryBuilder.ProcessorIncomingItems.Add(ctx, int64(incoming), metric.WithAttributes(or.otelAttrs...)) - or.telemetryBuilder.ProcessorOutgoingItems.Add(ctx, int64(outgoing), metric.WithAttributes(or.otelAttrs...)) + or.telemetryBuilder.ProcessorIncomingItems.Add(ctx, int64(incoming), metric.WithAttributeSet(or.otelAttrs)) + or.telemetryBuilder.ProcessorOutgoingItems.Add(ctx, int64(outgoing), metric.WithAttributeSet(or.otelAttrs)) } diff --git a/receiver/receiverhelper/obsreport.go b/receiver/receiverhelper/obsreport.go index c92c464ff53..b483c19be3f 100644 --- a/receiver/receiverhelper/obsreport.go +++ b/receiver/receiverhelper/obsreport.go @@ -27,7 +27,7 @@ type ObsReport struct { longLivedCtx bool tracer trace.Tracer - otelAttrs []attribute.KeyValue + otelAttrs attribute.Set telemetryBuilder *metadata.TelemetryBuilder } @@ -60,10 +60,10 @@ func newReceiver(cfg ObsReportSettings) (*ObsReport, error) { longLivedCtx: cfg.LongLivedCtx, tracer: cfg.ReceiverCreateSettings.TracerProvider.Tracer(cfg.ReceiverID.String()), - otelAttrs: []attribute.KeyValue{ + otelAttrs: attribute.NewSet( attribute.String(internal.ReceiverKey, cfg.ReceiverID.String()), attribute.String(internal.TransportKey, cfg.Transport), - }, + ), telemetryBuilder: telemetryBuilder, }, nil } @@ -207,6 +207,6 @@ func (rec *ObsReport) recordMetrics(receiverCtx context.Context, signal pipeline refusedMeasure = rec.telemetryBuilder.ReceiverRefusedLogRecords } - acceptedMeasure.Add(receiverCtx, int64(numAccepted), metric.WithAttributes(rec.otelAttrs...)) - refusedMeasure.Add(receiverCtx, int64(numRefused), metric.WithAttributes(rec.otelAttrs...)) + acceptedMeasure.Add(receiverCtx, int64(numAccepted), metric.WithAttributeSet(rec.otelAttrs)) + refusedMeasure.Add(receiverCtx, int64(numRefused), metric.WithAttributeSet(rec.otelAttrs)) } diff --git a/receiver/scraperhelper/obsreport.go b/receiver/scraperhelper/obsreport.go index cce7f49478e..0424cde39bc 100644 --- a/receiver/scraperhelper/obsreport.go +++ b/receiver/scraperhelper/obsreport.go @@ -26,7 +26,7 @@ type obsReport struct { scraper component.ID tracer trace.Tracer - otelAttrs []attribute.KeyValue + otelAttrs attribute.Set telemetryBuilder *metadata.TelemetryBuilder } @@ -47,10 +47,10 @@ func newScraper(cfg obsReportSettings) (*obsReport, error) { scraper: cfg.Scraper, tracer: cfg.ReceiverCreateSettings.TracerProvider.Tracer(cfg.Scraper.String()), - otelAttrs: []attribute.KeyValue{ + otelAttrs: attribute.NewSet( attribute.String(internal.ReceiverKey, cfg.ReceiverID.String()), attribute.String(internal.ScraperKey, cfg.Scraper.String()), - }, + ), telemetryBuilder: telemetryBuilder, }, nil } @@ -103,6 +103,6 @@ func (s *obsReport) EndMetricsOp( } func (s *obsReport) recordMetrics(scraperCtx context.Context, numScrapedMetrics, numErroredMetrics int) { - s.telemetryBuilder.ScraperScrapedMetricPoints.Add(scraperCtx, int64(numScrapedMetrics), metric.WithAttributes(s.otelAttrs...)) - s.telemetryBuilder.ScraperErroredMetricPoints.Add(scraperCtx, int64(numErroredMetrics), metric.WithAttributes(s.otelAttrs...)) + s.telemetryBuilder.ScraperScrapedMetricPoints.Add(scraperCtx, int64(numScrapedMetrics), metric.WithAttributeSet(s.otelAttrs)) + s.telemetryBuilder.ScraperErroredMetricPoints.Add(scraperCtx, int64(numErroredMetrics), metric.WithAttributeSet(s.otelAttrs)) } diff --git a/service/telemetry/internal/otelinit/config.go b/service/telemetry/internal/otelinit/config.go index eec13808e64..a8983886038 100644 --- a/service/telemetry/internal/otelinit/config.go +++ b/service/telemetry/internal/otelinit/config.go @@ -48,17 +48,17 @@ const ( var ( // GRPCUnacceptableKeyValues is a list of high cardinality grpc attributes that should be filtered out. - GRPCUnacceptableKeyValues = []attribute.KeyValue{ + GRPCUnacceptableKeyValues = attribute.NewSet( attribute.String(semconv.AttributeNetSockPeerAddr, ""), attribute.String(semconv.AttributeNetSockPeerPort, ""), attribute.String(semconv.AttributeNetSockPeerName, ""), - } + ) // HTTPUnacceptableKeyValues is a list of high cardinality http attributes that should be filtered out. - HTTPUnacceptableKeyValues = []attribute.KeyValue{ + HTTPUnacceptableKeyValues = attribute.NewSet( attribute.String(semconv.AttributeNetHostName, ""), attribute.String(semconv.AttributeNetHostPort, ""), - } + ) errNoValidMetricExporter = errors.New("no valid metric exporter") ) @@ -123,18 +123,17 @@ func disableHighCardinalityViews(disableHighCardinality bool) []sdkmetric.View { sdkmetric.NewView( sdkmetric.Instrument{Scope: instrumentation.Scope{Name: GRPCInstrumentation}}, sdkmetric.Stream{ - AttributeFilter: cardinalityFilter(GRPCUnacceptableKeyValues...), + AttributeFilter: cardinalityFilter(GRPCUnacceptableKeyValues), }), sdkmetric.NewView( sdkmetric.Instrument{Scope: instrumentation.Scope{Name: HTTPInstrumentation}}, sdkmetric.Stream{ - AttributeFilter: cardinalityFilter(HTTPUnacceptableKeyValues...), + AttributeFilter: cardinalityFilter(HTTPUnacceptableKeyValues), }), } } -func cardinalityFilter(kvs ...attribute.KeyValue) attribute.Filter { - filter := attribute.NewSet(kvs...) +func cardinalityFilter(filter attribute.Set) attribute.Filter { return func(kv attribute.KeyValue) bool { return !filter.HasValue(kv.Key) } diff --git a/service/telemetry/metrics_test.go b/service/telemetry/metrics_test.go index 3446ad219d6..1f012b00b29 100644 --- a/service/telemetry/metrics_test.go +++ b/service/telemetry/metrics_test.go @@ -258,11 +258,11 @@ func createTestMetrics(t *testing.T, mp metric.MeterProvider) { grpcExampleCounter, err := mp.Meter(otelinit.GRPCInstrumentation).Int64Counter(metricPrefix + grpcPrefix + counterName) require.NoError(t, err) - grpcExampleCounter.Add(context.Background(), 11, metric.WithAttributes(otelinit.GRPCUnacceptableKeyValues...)) + grpcExampleCounter.Add(context.Background(), 11, metric.WithAttributeSet(otelinit.GRPCUnacceptableKeyValues)) httpExampleCounter, err := mp.Meter(otelinit.HTTPInstrumentation).Int64Counter(metricPrefix + httpPrefix + counterName) require.NoError(t, err) - httpExampleCounter.Add(context.Background(), 10, metric.WithAttributes(otelinit.HTTPUnacceptableKeyValues...)) + httpExampleCounter.Add(context.Background(), 10, metric.WithAttributeSet(otelinit.HTTPUnacceptableKeyValues)) } func getMetricsFromPrometheus(t *testing.T, handler http.Handler) map[string]*io_prometheus_client.MetricFamily {