From dab1c33c333a31854c149e261e7ede3af316885a Mon Sep 17 00:00:00 2001 From: Greg Kalapos Date: Thu, 28 Nov 2024 16:41:41 +0100 Subject: [PATCH 1/7] Enrich root spans that represent a dependency --- enrichments/trace/internal/elastic/span.go | 34 +++++ .../trace/internal/elastic/span_test.go | 140 ++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index f352adf..02f70e8 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -196,6 +196,7 @@ func (s *spanEnrichmentContext) Enrich(span ptrace.Span, cfg config.Config) { func (s *spanEnrichmentContext) enrich(span ptrace.Span, cfg config.Config) { if s.isTransaction { s.enrichTransaction(span, cfg.Transaction) + s.enrichExitSpanTransaction(span, cfg) } else { s.enrichSpan(span, cfg.Span) } @@ -244,6 +245,39 @@ func (s *spanEnrichmentContext) enrichTransaction( } } +// In OTel a root span can represent an outgoing call or a producer span +// In such cases, the span is still mapped into a transaction, but such spans are enriched +// with additional attributes that are specific to the outgoing call or producer span. +func (s *spanEnrichmentContext) enrichExitSpanTransaction( + span ptrace.Span, + cfg config.Config, +) { + if span.Kind() == ptrace.SpanKindClient || span.Kind() == ptrace.SpanKindProducer { + if cfg.Span.TypeSubtype.Enabled { + s.setSpanTypeSubtype(span) + } + if cfg.Span.ServiceTarget.Enabled { + s.setServiceTarget(span) + } + if cfg.Span.DestinationService.Enabled { + s.setDestinationService(span) + } + if cfg.Span.Name.Enabled { + span.Attributes().PutStr(AttributeSpanName, span.Name()) + } + if cfg.Transaction.Type.Enabled { + spanTypeAttr, hasType := span.Attributes().Get(AttributeSpanType) + if hasType { + transactionType := spanTypeAttr.Str() + if spanSubtypeAttr, hasSubType := span.Attributes().Get(AttributeSpanSubtype); hasSubType { + transactionType += "." + spanSubtypeAttr.Str() + } + span.Attributes().PutStr(AttributeTransactionType, transactionType) + } + } + } +} + func (s *spanEnrichmentContext) enrichSpan( span ptrace.Span, cfg config.ElasticSpanConfig, diff --git a/enrichments/trace/internal/elastic/span_test.go b/enrichments/trace/internal/elastic/span_test.go index 591c1a0..9e5ea17 100644 --- a/enrichments/trace/internal/elastic/span_test.go +++ b/enrichments/trace/internal/elastic/span_test.go @@ -388,6 +388,146 @@ func TestElasticTransactionEnrich(t *testing.T) { } } +// Tests root spans that represent a dependency and are mapped to a transaction. +func TestRootSpanAsDependencyEnrich(t *testing.T) { + for _, tc := range []struct { + name string + input ptrace.Span + config config.Config + enrichedAttrs map[string]any + expectedSpanLinks *ptrace.SpanLinkSlice + }{ + { + name: "outgoing_http_root_span", + input: func() ptrace.Span { + span := ptrace.NewSpan() + span.SetName("rootClientSpan") + span.SetSpanID([8]byte{1}) + span.SetKind(ptrace.SpanKindClient) + span.Attributes().PutStr(semconv.AttributeHTTPMethod, "GET") + span.Attributes().PutStr(semconv.AttributeHTTPURL, "http://localhost:8080") + span.Attributes().PutInt(semconv.AttributeHTTPResponseStatusCode, 200) + span.Attributes().PutStr(semconv.AttributeNetworkProtocolVersion, "1.1") + return span + }(), + config: config.Enabled(), + enrichedAttrs: map[string]any{ + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: "transaction", + AttributeSpanType: "external", + AttributeSpanSubtype: "http", + AttributeSpanDestinationServiceResource: "localhost:8080", + AttributeSpanName: "rootClientSpan", + AttributeEventOutcome: "success", + AttributeSuccessCount: int64(1), + AttributeServiceTargetName: "localhost:8080", + AttributeServiceTargetType: "http", + AttributeTransactionID: "0100000000000000", + AttributeTransactionDurationUs: int64(0), + AttributeTransactionRepresentativeCount: float64(1), + AttributeTransactionResult: "HTTP 2xx", + AttributeTransactionType: "external.http", + AttributeTransactionSampled: true, + AttributeTransactionRoot: true, + }, + }, + { + name: "db_root_span", + input: func() ptrace.Span { + span := ptrace.NewSpan() + span.SetName("rootClientSpan") + span.SetSpanID([8]byte{1}) + span.SetKind(ptrace.SpanKindClient) + span.Attributes().PutStr(semconv.AttributeDBSystem, "mssql") + + span.Attributes().PutStr(semconv.AttributeDBName, "myDb") + span.Attributes().PutStr(semconv.AttributeDBOperation, "SELECT") + span.Attributes().PutStr(semconv.AttributeDBStatement, "SELECT * FROM wuser_table") + return span + }(), + config: config.Enabled(), + enrichedAttrs: map[string]any{ + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: "transaction", + AttributeSpanType: "db", + AttributeSpanSubtype: "mssql", + AttributeSpanDestinationServiceResource: "mssql", + AttributeSpanName: "rootClientSpan", + AttributeEventOutcome: "success", + AttributeSuccessCount: int64(1), + AttributeServiceTargetName: "myDb", + AttributeServiceTargetType: "mssql", + AttributeTransactionID: "0100000000000000", + AttributeTransactionDurationUs: int64(0), + AttributeTransactionRepresentativeCount: float64(1), + AttributeTransactionResult: "Success", + AttributeTransactionType: "db.mssql", + AttributeTransactionSampled: true, + AttributeTransactionRoot: true, + }, + }, + { + name: "producer_messaging_span", + input: func() ptrace.Span { + span := ptrace.NewSpan() + span.SetName("rootClientSpan") + span.SetSpanID([8]byte{1}) + span.SetKind(ptrace.SpanKindProducer) + + span.Attributes().PutStr(semconv.AttributeServerAddress, "myServer") + span.Attributes().PutStr(semconv.AttributeServerPort, "1234") + span.Attributes().PutStr(semconv.AttributeMessagingSystem, "rabbitmq") + span.Attributes().PutStr(semconv.AttributeMessagingDestinationName, "T") + span.Attributes().PutStr(semconv.AttributeMessagingOperation, "publish") + span.Attributes().PutStr(semconv.AttributeMessagingClientID, "a") + return span + }(), + config: config.Enabled(), + enrichedAttrs: map[string]any{ + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: "transaction", + AttributeSpanType: "messaging", + AttributeSpanSubtype: "rabbitmq", + AttributeSpanDestinationServiceResource: "rabbitmq/T", + AttributeSpanName: "rootClientSpan", + AttributeEventOutcome: "success", + AttributeSuccessCount: int64(1), + AttributeServiceTargetName: "T", + AttributeServiceTargetType: "rabbitmq", + AttributeTransactionID: "0100000000000000", + AttributeTransactionDurationUs: int64(0), + AttributeTransactionRepresentativeCount: float64(1), + AttributeTransactionResult: "Success", + AttributeTransactionType: "messaging.rabbitmq", + AttributeTransactionSampled: true, + AttributeTransactionRoot: true, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + expectedSpan := ptrace.NewSpan() + tc.input.CopyTo(expectedSpan) + + // Merge with the expected attributes and override the span links. + for k, v := range tc.enrichedAttrs { + expectedSpan.Attributes().PutEmpty(k).FromRaw(v) + } + // Override span links + if tc.expectedSpanLinks != nil { + tc.expectedSpanLinks.CopyTo(expectedSpan.Links()) + } else { + expectedSpan.Links().RemoveIf(func(_ ptrace.SpanLink) bool { return true }) + } + + EnrichSpan(tc.input, tc.config) + assert.NoError(t, ptracetest.CompareSpan(expectedSpan, tc.input)) + }) + } +} + // Tests the enrichment logic for elastic's span definition. func TestElasticSpanEnrich(t *testing.T) { now := time.Unix(3600, 0) From 51005a18bb9a467712341da37a66d16da4b79912 Mon Sep 17 00:00:00 2001 From: Greg Kalapos Date: Fri, 29 Nov 2024 19:05:55 +0100 Subject: [PATCH 2/7] Merge enrichSpan and enrichExitSpanTransaction methods --- enrichments/trace/internal/elastic/span.go | 46 +++++++++++++------ .../trace/internal/elastic/span_test.go | 6 +++ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index 02f70e8..f47837b 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -194,11 +194,17 @@ func (s *spanEnrichmentContext) Enrich(span ptrace.Span, cfg config.Config) { } func (s *spanEnrichmentContext) enrich(span ptrace.Span, cfg config.Config) { + + // In OTel, a local root span can represent an outgoing call or a producer span. + // In such cases, the span is still mapped into a transaction, but enriched + // with additional attributes that are specific to the outgoing call or producer span. + isExitRootSpan := s.isTransaction && span.Kind() == ptrace.SpanKindClient || span.Kind() == ptrace.SpanKindProducer + if s.isTransaction { s.enrichTransaction(span, cfg.Transaction) - s.enrichExitSpanTransaction(span, cfg) - } else { - s.enrichSpan(span, cfg.Span) + } + if !s.isTransaction || isExitRootSpan { + s.enrichSpan(span, cfg, isExitRootSpan) } } @@ -245,8 +251,8 @@ func (s *spanEnrichmentContext) enrichTransaction( } } -// In OTel a root span can represent an outgoing call or a producer span -// In such cases, the span is still mapped into a transaction, but such spans are enriched +// In OTel, a local span can represent an outgoing call or a producer span. +// In such cases, the span is still mapped into a transaction, but enriched // with additional attributes that are specific to the outgoing call or producer span. func (s *spanEnrichmentContext) enrichExitSpanTransaction( span ptrace.Span, @@ -280,7 +286,8 @@ func (s *spanEnrichmentContext) enrichExitSpanTransaction( func (s *spanEnrichmentContext) enrichSpan( span ptrace.Span, - cfg config.ElasticSpanConfig, + cfg config.Config, + isExitRootSpan bool, ) { if cfg.TimestampUs.Enabled { span.Attributes().PutInt(elasticattr.TimestampUs, getTimestampUs(span.StartTimestamp())) @@ -288,31 +295,42 @@ func (s *spanEnrichmentContext) enrichSpan( if cfg.Name.Enabled { span.Attributes().PutStr(elasticattr.SpanName, span.Name()) } - if cfg.ProcessorEvent.Enabled { - span.Attributes().PutStr(elasticattr.ProcessorEvent, "span") - } if cfg.RepresentativeCount.Enabled { repCount := getRepresentativeCount(span.TraceState().AsRaw()) span.Attributes().PutDouble(elasticattr.SpanRepresentativeCount, repCount) } - if cfg.TypeSubtype.Enabled { + if cfg.Span.TypeSubtype.Enabled { s.setSpanTypeSubtype(span) } - if cfg.EventOutcome.Enabled { + if cfg.Span.EventOutcome.Enabled { s.setEventOutcome(span) } if cfg.DurationUs.Enabled { span.Attributes().PutInt(elasticattr.SpanDurationUs, getDurationUs(span)) } - if cfg.ServiceTarget.Enabled { + if cfg.Span.ServiceTarget.Enabled { s.setServiceTarget(span) } - if cfg.DestinationService.Enabled { + if cfg.Span.DestinationService.Enabled { s.setDestinationService(span) } - if cfg.InferredSpans.Enabled { + if cfg.Span.InferredSpans.Enabled { s.setInferredSpans(span) } + if cfg.Span.ProcessorEvent.Enabled && !isExitRootSpan { + span.Attributes().PutStr(AttributeProcessorEvent, "span") + } + + if isExitRootSpan && cfg.Transaction.Type.Enabled { + spanTypeAttr, hasType := span.Attributes().Get(AttributeSpanType) + if hasType { + transactionType := spanTypeAttr.Str() + if spanSubtypeAttr, hasSubType := span.Attributes().Get(AttributeSpanSubtype); hasSubType { + transactionType += "." + spanSubtypeAttr.Str() + } + span.Attributes().PutStr(AttributeTransactionType, transactionType) + } + } } // normalizeAttributes sets any dependent attributes that diff --git a/enrichments/trace/internal/elastic/span_test.go b/enrichments/trace/internal/elastic/span_test.go index 9e5ea17..01486cb 100644 --- a/enrichments/trace/internal/elastic/span_test.go +++ b/enrichments/trace/internal/elastic/span_test.go @@ -430,6 +430,8 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { AttributeTransactionType: "external.http", AttributeTransactionSampled: true, AttributeTransactionRoot: true, + AttributeSpanDurationUs: int64(0), + AttributeSpanRepresentativeCount: float64(1), }, }, { @@ -466,6 +468,8 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { AttributeTransactionType: "db.mssql", AttributeTransactionSampled: true, AttributeTransactionRoot: true, + AttributeSpanDurationUs: int64(0), + AttributeSpanRepresentativeCount: float64(1), }, }, { @@ -504,6 +508,8 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { AttributeTransactionType: "messaging.rabbitmq", AttributeTransactionSampled: true, AttributeTransactionRoot: true, + AttributeSpanDurationUs: int64(0), + AttributeSpanRepresentativeCount: float64(1), }, }, } { From 7a82020bd25d53726b4c95cfab31a82698f9c4d9 Mon Sep 17 00:00:00 2001 From: Greg Kalapos Date: Fri, 29 Nov 2024 19:10:17 +0100 Subject: [PATCH 3/7] Update span.go --- enrichments/trace/internal/elastic/span.go | 33 ---------------------- 1 file changed, 33 deletions(-) diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index f47837b..3813ca6 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -251,39 +251,6 @@ func (s *spanEnrichmentContext) enrichTransaction( } } -// In OTel, a local span can represent an outgoing call or a producer span. -// In such cases, the span is still mapped into a transaction, but enriched -// with additional attributes that are specific to the outgoing call or producer span. -func (s *spanEnrichmentContext) enrichExitSpanTransaction( - span ptrace.Span, - cfg config.Config, -) { - if span.Kind() == ptrace.SpanKindClient || span.Kind() == ptrace.SpanKindProducer { - if cfg.Span.TypeSubtype.Enabled { - s.setSpanTypeSubtype(span) - } - if cfg.Span.ServiceTarget.Enabled { - s.setServiceTarget(span) - } - if cfg.Span.DestinationService.Enabled { - s.setDestinationService(span) - } - if cfg.Span.Name.Enabled { - span.Attributes().PutStr(AttributeSpanName, span.Name()) - } - if cfg.Transaction.Type.Enabled { - spanTypeAttr, hasType := span.Attributes().Get(AttributeSpanType) - if hasType { - transactionType := spanTypeAttr.Str() - if spanSubtypeAttr, hasSubType := span.Attributes().Get(AttributeSpanSubtype); hasSubType { - transactionType += "." + spanSubtypeAttr.Str() - } - span.Attributes().PutStr(AttributeTransactionType, transactionType) - } - } - } -} - func (s *spanEnrichmentContext) enrichSpan( span ptrace.Span, cfg config.Config, From 2b9840c8cfc60e72196dd25aac6e975ef3f78179 Mon Sep 17 00:00:00 2001 From: Greg Kalapos Date: Mon, 9 Dec 2024 19:25:56 +0100 Subject: [PATCH 4/7] Set both `transaction` and `span` on root exit root spans --- enrichments/trace/internal/elastic/span.go | 10 ++++-- .../trace/internal/elastic/span_test.go | 33 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index 3813ca6..68b894f 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -284,8 +284,14 @@ func (s *spanEnrichmentContext) enrichSpan( if cfg.Span.InferredSpans.Enabled { s.setInferredSpans(span) } - if cfg.Span.ProcessorEvent.Enabled && !isExitRootSpan { - span.Attributes().PutStr(AttributeProcessorEvent, "span") + if cfg.Span.ProcessorEvent.Enabled { + if isExitRootSpan { + attrSlice := span.Attributes().PutEmptySlice(AttributeProcessorEvent) + attrSlice.AppendEmpty().SetStr("transaction") + attrSlice.AppendEmpty().SetStr("span") + } else { + span.Attributes().PutStr(AttributeProcessorEvent, "span") + } } if isExitRootSpan && cfg.Transaction.Type.Enabled { diff --git a/enrichments/trace/internal/elastic/span_test.go b/enrichments/trace/internal/elastic/span_test.go index 01486cb..b253150 100644 --- a/enrichments/trace/internal/elastic/span_test.go +++ b/enrichments/trace/internal/elastic/span_test.go @@ -412,9 +412,14 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: "transaction", + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: func() pcommon.Slice { + p := pcommon.NewSlice() + p.AppendEmpty().SetStr("transaction") + p.AppendEmpty().SetStr("span") + return p + }().AsRaw(), AttributeSpanType: "external", AttributeSpanSubtype: "http", AttributeSpanDestinationServiceResource: "localhost:8080", @@ -450,9 +455,14 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: "transaction", + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: func() pcommon.Slice { + p := pcommon.NewSlice() + p.AppendEmpty().SetStr("transaction") + p.AppendEmpty().SetStr("span") + return p + }().AsRaw(), AttributeSpanType: "db", AttributeSpanSubtype: "mssql", AttributeSpanDestinationServiceResource: "mssql", @@ -490,9 +500,14 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: "transaction", + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: func() pcommon.Slice { + p := pcommon.NewSlice() + p.AppendEmpty().SetStr("transaction") + p.AppendEmpty().SetStr("span") + return p + }().AsRaw(), AttributeSpanType: "messaging", AttributeSpanSubtype: "rabbitmq", AttributeSpanDestinationServiceResource: "rabbitmq/T", From c11f361c65662a3d09b392560efddb2b21f4bd5c Mon Sep 17 00:00:00 2001 From: Greg Kalapos Date: Mon, 3 Mar 2025 14:17:49 +0100 Subject: [PATCH 5/7] Remove using processor.event as multi value field --- enrichments/trace/internal/elastic/span.go | 10 ++---- .../trace/internal/elastic/span_test.go | 33 +++++-------------- 2 files changed, 11 insertions(+), 32 deletions(-) diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index 68b894f..3813ca6 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -284,14 +284,8 @@ func (s *spanEnrichmentContext) enrichSpan( if cfg.Span.InferredSpans.Enabled { s.setInferredSpans(span) } - if cfg.Span.ProcessorEvent.Enabled { - if isExitRootSpan { - attrSlice := span.Attributes().PutEmptySlice(AttributeProcessorEvent) - attrSlice.AppendEmpty().SetStr("transaction") - attrSlice.AppendEmpty().SetStr("span") - } else { - span.Attributes().PutStr(AttributeProcessorEvent, "span") - } + if cfg.Span.ProcessorEvent.Enabled && !isExitRootSpan { + span.Attributes().PutStr(AttributeProcessorEvent, "span") } if isExitRootSpan && cfg.Transaction.Type.Enabled { diff --git a/enrichments/trace/internal/elastic/span_test.go b/enrichments/trace/internal/elastic/span_test.go index b253150..01486cb 100644 --- a/enrichments/trace/internal/elastic/span_test.go +++ b/enrichments/trace/internal/elastic/span_test.go @@ -412,14 +412,9 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: func() pcommon.Slice { - p := pcommon.NewSlice() - p.AppendEmpty().SetStr("transaction") - p.AppendEmpty().SetStr("span") - return p - }().AsRaw(), + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: "transaction", AttributeSpanType: "external", AttributeSpanSubtype: "http", AttributeSpanDestinationServiceResource: "localhost:8080", @@ -455,14 +450,9 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: func() pcommon.Slice { - p := pcommon.NewSlice() - p.AppendEmpty().SetStr("transaction") - p.AppendEmpty().SetStr("span") - return p - }().AsRaw(), + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: "transaction", AttributeSpanType: "db", AttributeSpanSubtype: "mssql", AttributeSpanDestinationServiceResource: "mssql", @@ -500,14 +490,9 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: func() pcommon.Slice { - p := pcommon.NewSlice() - p.AppendEmpty().SetStr("transaction") - p.AppendEmpty().SetStr("span") - return p - }().AsRaw(), + AttributeTimestampUs: int64(0), + AttributeTransactionName: "rootClientSpan", + AttributeProcessorEvent: "transaction", AttributeSpanType: "messaging", AttributeSpanSubtype: "rabbitmq", AttributeSpanDestinationServiceResource: "rabbitmq/T", From 6ac27031099764ced7c818ded5ccc269e6195e81 Mon Sep 17 00:00:00 2001 From: Greg Kalapos Date: Mon, 3 Mar 2025 14:46:11 +0100 Subject: [PATCH 6/7] Adapt to main --- enrichments/trace/internal/elastic/span.go | 16 +- .../trace/internal/elastic/span_test.go | 148 +++++++++--------- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index 3813ca6..a3f6cec 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -256,13 +256,13 @@ func (s *spanEnrichmentContext) enrichSpan( cfg config.Config, isExitRootSpan bool, ) { - if cfg.TimestampUs.Enabled { + if cfg.Span.TimestampUs.Enabled { span.Attributes().PutInt(elasticattr.TimestampUs, getTimestampUs(span.StartTimestamp())) } - if cfg.Name.Enabled { + if cfg.Span.Name.Enabled { span.Attributes().PutStr(elasticattr.SpanName, span.Name()) } - if cfg.RepresentativeCount.Enabled { + if cfg.Span.RepresentativeCount.Enabled { repCount := getRepresentativeCount(span.TraceState().AsRaw()) span.Attributes().PutDouble(elasticattr.SpanRepresentativeCount, repCount) } @@ -272,7 +272,7 @@ func (s *spanEnrichmentContext) enrichSpan( if cfg.Span.EventOutcome.Enabled { s.setEventOutcome(span) } - if cfg.DurationUs.Enabled { + if cfg.Span.DurationUs.Enabled { span.Attributes().PutInt(elasticattr.SpanDurationUs, getDurationUs(span)) } if cfg.Span.ServiceTarget.Enabled { @@ -285,17 +285,17 @@ func (s *spanEnrichmentContext) enrichSpan( s.setInferredSpans(span) } if cfg.Span.ProcessorEvent.Enabled && !isExitRootSpan { - span.Attributes().PutStr(AttributeProcessorEvent, "span") + span.Attributes().PutStr(elasticattr.ProcessorEvent, "span") } if isExitRootSpan && cfg.Transaction.Type.Enabled { - spanTypeAttr, hasType := span.Attributes().Get(AttributeSpanType) + spanTypeAttr, hasType := span.Attributes().Get(elasticattr.SpanType) if hasType { transactionType := spanTypeAttr.Str() - if spanSubtypeAttr, hasSubType := span.Attributes().Get(AttributeSpanSubtype); hasSubType { + if spanSubtypeAttr, hasSubType := span.Attributes().Get(elasticattr.SpanSubtype); hasSubType { transactionType += "." + spanSubtypeAttr.Str() } - span.Attributes().PutStr(AttributeTransactionType, transactionType) + span.Attributes().PutStr(elasticattr.TransactionType, transactionType) } } } diff --git a/enrichments/trace/internal/elastic/span_test.go b/enrichments/trace/internal/elastic/span_test.go index 01486cb..1b03335 100644 --- a/enrichments/trace/internal/elastic/span_test.go +++ b/enrichments/trace/internal/elastic/span_test.go @@ -404,34 +404,34 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { span.SetName("rootClientSpan") span.SetSpanID([8]byte{1}) span.SetKind(ptrace.SpanKindClient) - span.Attributes().PutStr(semconv.AttributeHTTPMethod, "GET") - span.Attributes().PutStr(semconv.AttributeHTTPURL, "http://localhost:8080") - span.Attributes().PutInt(semconv.AttributeHTTPResponseStatusCode, 200) - span.Attributes().PutStr(semconv.AttributeNetworkProtocolVersion, "1.1") + span.Attributes().PutStr(semconv27.AttributeHTTPRequestMethod, "GET") + span.Attributes().PutStr(semconv27.AttributeURLFull, "http://localhost:8080") + span.Attributes().PutInt(semconv27.AttributeHTTPResponseStatusCode, 200) + span.Attributes().PutStr(semconv27.AttributeNetworkProtocolVersion, "1.1") return span }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: "transaction", - AttributeSpanType: "external", - AttributeSpanSubtype: "http", - AttributeSpanDestinationServiceResource: "localhost:8080", - AttributeSpanName: "rootClientSpan", - AttributeEventOutcome: "success", - AttributeSuccessCount: int64(1), - AttributeServiceTargetName: "localhost:8080", - AttributeServiceTargetType: "http", - AttributeTransactionID: "0100000000000000", - AttributeTransactionDurationUs: int64(0), - AttributeTransactionRepresentativeCount: float64(1), - AttributeTransactionResult: "HTTP 2xx", - AttributeTransactionType: "external.http", - AttributeTransactionSampled: true, - AttributeTransactionRoot: true, - AttributeSpanDurationUs: int64(0), - AttributeSpanRepresentativeCount: float64(1), + elasticattr.TimestampUs: int64(0), + elasticattr.TransactionName: "rootClientSpan", + elasticattr.ProcessorEvent: "transaction", + elasticattr.SpanType: "external", + elasticattr.SpanSubtype: "http", + elasticattr.SpanDestinationServiceResource: "localhost:8080", + elasticattr.SpanName: "rootClientSpan", + elasticattr.EventOutcome: "success", + elasticattr.SuccessCount: int64(1), + elasticattr.ServiceTargetName: "localhost:8080", + elasticattr.ServiceTargetType: "http", + elasticattr.TransactionID: "0100000000000000", + elasticattr.TransactionDurationUs: int64(0), + elasticattr.TransactionRepresentativeCount: float64(1), + elasticattr.TransactionResult: "HTTP 2xx", + elasticattr.TransactionType: "external.http", + elasticattr.TransactionSampled: true, + elasticattr.TransactionRoot: true, + elasticattr.SpanDurationUs: int64(0), + elasticattr.SpanRepresentativeCount: float64(1), }, }, { @@ -441,35 +441,35 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { span.SetName("rootClientSpan") span.SetSpanID([8]byte{1}) span.SetKind(ptrace.SpanKindClient) - span.Attributes().PutStr(semconv.AttributeDBSystem, "mssql") + span.Attributes().PutStr(semconv25.AttributeDBSystem, "mssql") - span.Attributes().PutStr(semconv.AttributeDBName, "myDb") - span.Attributes().PutStr(semconv.AttributeDBOperation, "SELECT") - span.Attributes().PutStr(semconv.AttributeDBStatement, "SELECT * FROM wuser_table") + span.Attributes().PutStr(semconv25.AttributeDBName, "myDb") + span.Attributes().PutStr(semconv25.AttributeDBOperation, "SELECT") + span.Attributes().PutStr(semconv25.AttributeDBStatement, "SELECT * FROM wuser_table") return span }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: "transaction", - AttributeSpanType: "db", - AttributeSpanSubtype: "mssql", - AttributeSpanDestinationServiceResource: "mssql", - AttributeSpanName: "rootClientSpan", - AttributeEventOutcome: "success", - AttributeSuccessCount: int64(1), - AttributeServiceTargetName: "myDb", - AttributeServiceTargetType: "mssql", - AttributeTransactionID: "0100000000000000", - AttributeTransactionDurationUs: int64(0), - AttributeTransactionRepresentativeCount: float64(1), - AttributeTransactionResult: "Success", - AttributeTransactionType: "db.mssql", - AttributeTransactionSampled: true, - AttributeTransactionRoot: true, - AttributeSpanDurationUs: int64(0), - AttributeSpanRepresentativeCount: float64(1), + elasticattr.TimestampUs: int64(0), + elasticattr.TransactionName: "rootClientSpan", + elasticattr.ProcessorEvent: "transaction", + elasticattr.SpanType: "db", + elasticattr.SpanSubtype: "mssql", + elasticattr.SpanDestinationServiceResource: "mssql", + elasticattr.SpanName: "rootClientSpan", + elasticattr.EventOutcome: "success", + elasticattr.SuccessCount: int64(1), + elasticattr.ServiceTargetName: "myDb", + elasticattr.ServiceTargetType: "mssql", + elasticattr.TransactionID: "0100000000000000", + elasticattr.TransactionDurationUs: int64(0), + elasticattr.TransactionRepresentativeCount: float64(1), + elasticattr.TransactionResult: "Success", + elasticattr.TransactionType: "db.mssql", + elasticattr.TransactionSampled: true, + elasticattr.TransactionRoot: true, + elasticattr.SpanDurationUs: int64(0), + elasticattr.SpanRepresentativeCount: float64(1), }, }, { @@ -480,36 +480,36 @@ func TestRootSpanAsDependencyEnrich(t *testing.T) { span.SetSpanID([8]byte{1}) span.SetKind(ptrace.SpanKindProducer) - span.Attributes().PutStr(semconv.AttributeServerAddress, "myServer") - span.Attributes().PutStr(semconv.AttributeServerPort, "1234") - span.Attributes().PutStr(semconv.AttributeMessagingSystem, "rabbitmq") - span.Attributes().PutStr(semconv.AttributeMessagingDestinationName, "T") - span.Attributes().PutStr(semconv.AttributeMessagingOperation, "publish") - span.Attributes().PutStr(semconv.AttributeMessagingClientID, "a") + span.Attributes().PutStr(semconv25.AttributeServerAddress, "myServer") + span.Attributes().PutStr(semconv25.AttributeServerPort, "1234") + span.Attributes().PutStr(semconv25.AttributeMessagingSystem, "rabbitmq") + span.Attributes().PutStr(semconv25.AttributeMessagingDestinationName, "T") + span.Attributes().PutStr(semconv25.AttributeMessagingOperation, "publish") + span.Attributes().PutStr(semconv25.AttributeMessagingClientID, "a") return span }(), config: config.Enabled(), enrichedAttrs: map[string]any{ - AttributeTimestampUs: int64(0), - AttributeTransactionName: "rootClientSpan", - AttributeProcessorEvent: "transaction", - AttributeSpanType: "messaging", - AttributeSpanSubtype: "rabbitmq", - AttributeSpanDestinationServiceResource: "rabbitmq/T", - AttributeSpanName: "rootClientSpan", - AttributeEventOutcome: "success", - AttributeSuccessCount: int64(1), - AttributeServiceTargetName: "T", - AttributeServiceTargetType: "rabbitmq", - AttributeTransactionID: "0100000000000000", - AttributeTransactionDurationUs: int64(0), - AttributeTransactionRepresentativeCount: float64(1), - AttributeTransactionResult: "Success", - AttributeTransactionType: "messaging.rabbitmq", - AttributeTransactionSampled: true, - AttributeTransactionRoot: true, - AttributeSpanDurationUs: int64(0), - AttributeSpanRepresentativeCount: float64(1), + elasticattr.TimestampUs: int64(0), + elasticattr.TransactionName: "rootClientSpan", + elasticattr.ProcessorEvent: "transaction", + elasticattr.SpanType: "messaging", + elasticattr.SpanSubtype: "rabbitmq", + elasticattr.SpanDestinationServiceResource: "rabbitmq/T", + elasticattr.SpanName: "rootClientSpan", + elasticattr.EventOutcome: "success", + elasticattr.SuccessCount: int64(1), + elasticattr.ServiceTargetName: "T", + elasticattr.ServiceTargetType: "rabbitmq", + elasticattr.TransactionID: "0100000000000000", + elasticattr.TransactionDurationUs: int64(0), + elasticattr.TransactionRepresentativeCount: float64(1), + elasticattr.TransactionResult: "Success", + elasticattr.TransactionType: "messaging.rabbitmq", + elasticattr.TransactionSampled: true, + elasticattr.TransactionRoot: true, + elasticattr.SpanDurationUs: int64(0), + elasticattr.SpanRepresentativeCount: float64(1), }, }, } { From 970eab02862def156046789c78919cc4d8acb860 Mon Sep 17 00:00:00 2001 From: Greg Kalapos Date: Mon, 3 Mar 2025 16:11:10 +0100 Subject: [PATCH 7/7] Review feedback --- enrichments/trace/internal/elastic/span.go | 46 +++++++++++----------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/enrichments/trace/internal/elastic/span.go b/enrichments/trace/internal/elastic/span.go index a3f6cec..ca694f4 100644 --- a/enrichments/trace/internal/elastic/span.go +++ b/enrichments/trace/internal/elastic/span.go @@ -204,7 +204,7 @@ func (s *spanEnrichmentContext) enrich(span ptrace.Span, cfg config.Config) { s.enrichTransaction(span, cfg.Transaction) } if !s.isTransaction || isExitRootSpan { - s.enrichSpan(span, cfg, isExitRootSpan) + s.enrichSpan(span, cfg.Span, cfg.Transaction.Type.Enabled, isExitRootSpan) } } @@ -253,47 +253,49 @@ func (s *spanEnrichmentContext) enrichTransaction( func (s *spanEnrichmentContext) enrichSpan( span ptrace.Span, - cfg config.Config, + cfg config.ElasticSpanConfig, + transactionTypeEnabled bool, isExitRootSpan bool, ) { - if cfg.Span.TimestampUs.Enabled { + var spanType, spanSubtype string + + if cfg.TimestampUs.Enabled { span.Attributes().PutInt(elasticattr.TimestampUs, getTimestampUs(span.StartTimestamp())) } - if cfg.Span.Name.Enabled { + if cfg.Name.Enabled { span.Attributes().PutStr(elasticattr.SpanName, span.Name()) } - if cfg.Span.RepresentativeCount.Enabled { + if cfg.RepresentativeCount.Enabled { repCount := getRepresentativeCount(span.TraceState().AsRaw()) span.Attributes().PutDouble(elasticattr.SpanRepresentativeCount, repCount) } - if cfg.Span.TypeSubtype.Enabled { - s.setSpanTypeSubtype(span) + if cfg.TypeSubtype.Enabled { + spanType, spanSubtype = s.setSpanTypeSubtype(span) } - if cfg.Span.EventOutcome.Enabled { + if cfg.EventOutcome.Enabled { s.setEventOutcome(span) } - if cfg.Span.DurationUs.Enabled { + if cfg.DurationUs.Enabled { span.Attributes().PutInt(elasticattr.SpanDurationUs, getDurationUs(span)) } - if cfg.Span.ServiceTarget.Enabled { + if cfg.ServiceTarget.Enabled { s.setServiceTarget(span) } - if cfg.Span.DestinationService.Enabled { + if cfg.DestinationService.Enabled { s.setDestinationService(span) } - if cfg.Span.InferredSpans.Enabled { + if cfg.InferredSpans.Enabled { s.setInferredSpans(span) } - if cfg.Span.ProcessorEvent.Enabled && !isExitRootSpan { + if cfg.ProcessorEvent.Enabled && !isExitRootSpan { span.Attributes().PutStr(elasticattr.ProcessorEvent, "span") } - if isExitRootSpan && cfg.Transaction.Type.Enabled { - spanTypeAttr, hasType := span.Attributes().Get(elasticattr.SpanType) - if hasType { - transactionType := spanTypeAttr.Str() - if spanSubtypeAttr, hasSubType := span.Attributes().Get(elasticattr.SpanSubtype); hasSubType { - transactionType += "." + spanSubtypeAttr.Str() + if isExitRootSpan && transactionTypeEnabled { + if spanType != "" { + transactionType := spanType + if spanSubtype != "" { + transactionType += "." + spanSubtype } span.Attributes().PutStr(elasticattr.TransactionType, transactionType) } @@ -371,9 +373,7 @@ func (s *spanEnrichmentContext) setEventOutcome(span ptrace.Span) { span.Attributes().PutInt(elasticattr.SuccessCount, int64(successCount)) } -func (s *spanEnrichmentContext) setSpanTypeSubtype(span ptrace.Span) { - var spanType, spanSubtype string - +func (s *spanEnrichmentContext) setSpanTypeSubtype(span ptrace.Span) (spanType string, spanSubtype string) { switch { case s.isDB: spanType = "db" @@ -404,6 +404,8 @@ func (s *spanEnrichmentContext) setSpanTypeSubtype(span ptrace.Span) { if spanSubtype != "" { span.Attributes().PutStr(elasticattr.SpanSubtype, spanSubtype) } + + return spanType, spanSubtype } func (s *spanEnrichmentContext) setServiceTarget(span ptrace.Span) {