@@ -26,6 +26,7 @@ import (
2626
2727 "github.com/elastic/opentelemetry-lib/enrichments/trace/config"
2828 "github.com/google/go-cmp/cmp"
29+ "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/ptracetest"
2930 "github.com/stretchr/testify/assert"
3031 "go.opentelemetry.io/collector/pdata/pcommon"
3132 "go.opentelemetry.io/collector/pdata/ptrace"
@@ -48,10 +49,11 @@ func TestElasticTransactionEnrich(t *testing.T) {
4849 return span
4950 }
5051 for _ , tc := range []struct {
51- name string
52- input ptrace.Span
53- config config.ElasticTransactionConfig
54- enrichedAttrs map [string ]any
52+ name string
53+ input ptrace.Span
54+ config config.ElasticTransactionConfig
55+ enrichedAttrs map [string ]any
56+ expectedSpanLinks * ptrace.SpanLinkSlice
5557 }{
5658 {
5759 // test case gives a summary of what is emitted by default
@@ -319,20 +321,67 @@ func TestElasticTransactionEnrich(t *testing.T) {
319321 AttributeTransactionType : "messaging" ,
320322 },
321323 },
324+ {
325+ name : "inferred_spans" ,
326+ input : func () ptrace.Span {
327+ span := getElasticTxn ()
328+ span .SetName ("testtxn" )
329+ span .SetSpanID ([8 ]byte {1 })
330+ normalLink := span .Links ().AppendEmpty ()
331+ normalLink .SetSpanID ([8 ]byte {2 })
332+
333+ childLink := span .Links ().AppendEmpty ()
334+ childLink .SetSpanID ([8 ]byte {3 })
335+ childLink .Attributes ().PutBool ("is_child" , true )
336+
337+ childLink2 := span .Links ().AppendEmpty ()
338+ childLink2 .SetSpanID ([8 ]byte {4 })
339+ childLink2 .Attributes ().PutBool ("elastic.is_child" , true )
340+ return span
341+ }(),
342+ config : config .Enabled ().Transaction ,
343+ enrichedAttrs : map [string ]any {
344+ AttributeTimestampUs : startTs .AsTime ().UnixMicro (),
345+ AttributeTransactionSampled : true ,
346+ AttributeTransactionRoot : true ,
347+ AttributeTransactionID : "0100000000000000" ,
348+ AttributeTransactionName : "testtxn" ,
349+ AttributeProcessorEvent : "transaction" ,
350+ AttributeTransactionRepresentativeCount : float64 (1 ),
351+ AttributeTransactionDurationUs : expectedDuration .Microseconds (),
352+ AttributeEventOutcome : "success" ,
353+ AttributeSuccessCount : int64 (1 ),
354+ AttributeTransactionResult : "Success" ,
355+ AttributeTransactionType : "unknown" ,
356+ AttributeChildIDs : []any {"0300000000000000" , "0400000000000000" },
357+ },
358+ expectedSpanLinks : func () * ptrace.SpanLinkSlice {
359+ spanLinks := ptrace .NewSpanLinkSlice ()
360+ // Only the span link without `is_child` or `elastic.is_child` is expected
361+ spanLinks .AppendEmpty ().SetSpanID ([8 ]byte {2 })
362+ return & spanLinks
363+ }(),
364+ },
322365 } {
323366 t .Run (tc .name , func (t * testing.T ) {
324- // Merge existing input attrs with the attrs added
325- // by enrichment to get the expected attributes.
326- expectedAttrs := tc .input .Attributes ().AsRaw ()
367+ expectedSpan := ptrace .NewSpan ()
368+ tc .input .CopyTo (expectedSpan )
369+
370+ // Merge with the expected attributes and override the span links.
327371 for k , v := range tc .enrichedAttrs {
328- expectedAttrs [k ] = v
372+ expectedSpan .Attributes ().PutEmpty (k ).FromRaw (v )
373+ }
374+ // Override span links
375+ if tc .expectedSpanLinks != nil {
376+ tc .expectedSpanLinks .CopyTo (expectedSpan .Links ())
377+ } else {
378+ expectedSpan .Links ().RemoveIf (func (_ ptrace.SpanLink ) bool { return true })
329379 }
330380
331381 EnrichSpan (tc .input , config.Config {
332382 Transaction : tc .config ,
333383 })
334-
335- assert .Empty (t , cmp .Diff (expectedAttrs , tc .input .Attributes ().AsRaw ()))
384+ assert .NoError (t , ptracetest .CompareSpan (expectedSpan , tc .input ))
336385 })
337386 }
338387}
@@ -351,10 +400,11 @@ func TestElasticSpanEnrich(t *testing.T) {
351400 return span
352401 }
353402 for _ , tc := range []struct {
354- name string
355- input ptrace.Span
356- config config.ElasticSpanConfig
357- enrichedAttrs map [string ]any
403+ name string
404+ input ptrace.Span
405+ config config.ElasticSpanConfig
406+ enrichedAttrs map [string ]any
407+ expectedSpanLinks * ptrace.SpanLinkSlice
358408 }{
359409 {
360410 // test case gives a summary of what is emitted by default
@@ -827,20 +877,63 @@ func TestElasticSpanEnrich(t *testing.T) {
827877 AttributeSpanDestinationServiceResource : "testsvc" ,
828878 },
829879 },
880+ {
881+ name : "inferred_spans" ,
882+ input : func () ptrace.Span {
883+ span := getElasticSpan ()
884+ span .SetName ("testspan" )
885+ span .SetSpanID ([8 ]byte {1 })
886+ normalLink := span .Links ().AppendEmpty ()
887+ normalLink .SetSpanID ([8 ]byte {2 })
888+
889+ childLink := span .Links ().AppendEmpty ()
890+ childLink .SetSpanID ([8 ]byte {3 })
891+ childLink .Attributes ().PutBool ("is_child" , true )
892+
893+ childLink2 := span .Links ().AppendEmpty ()
894+ childLink2 .SetSpanID ([8 ]byte {4 })
895+ childLink2 .Attributes ().PutBool ("elastic.is_child" , true )
896+ return span
897+ }(),
898+ config : config .Enabled ().Span ,
899+ enrichedAttrs : map [string ]any {
900+ AttributeTimestampUs : startTs .AsTime ().UnixMicro (),
901+ AttributeSpanName : "testspan" ,
902+ AttributeProcessorEvent : "span" ,
903+ AttributeSpanRepresentativeCount : float64 (1 ),
904+ AttributeSpanType : "unknown" ,
905+ AttributeSpanDurationUs : expectedDuration .Microseconds (),
906+ AttributeEventOutcome : "success" ,
907+ AttributeSuccessCount : int64 (1 ),
908+ AttributeChildIDs : []any {"0300000000000000" , "0400000000000000" },
909+ },
910+ expectedSpanLinks : func () * ptrace.SpanLinkSlice {
911+ spanLinks := ptrace .NewSpanLinkSlice ()
912+ // Only the span link without `is_child` or `elastic.is_child` is expected
913+ spanLinks .AppendEmpty ().SetSpanID ([8 ]byte {2 })
914+ return & spanLinks
915+ }(),
916+ },
830917 } {
831918 t .Run (tc .name , func (t * testing.T ) {
832- // Merge existing input attrs with the attrs added
833- // by enrichment to get the expected attributes.
834- expectedAttrs := tc .input .Attributes ().AsRaw ()
919+ expectedSpan := ptrace .NewSpan ()
920+ tc .input .CopyTo (expectedSpan )
921+
922+ // Merge with the expected attributes and override the span links.
835923 for k , v := range tc .enrichedAttrs {
836- expectedAttrs [k ] = v
924+ expectedSpan .Attributes ().PutEmpty (k ).FromRaw (v )
925+ }
926+ // Override span links
927+ if tc .expectedSpanLinks != nil {
928+ tc .expectedSpanLinks .CopyTo (expectedSpan .Links ())
929+ } else {
930+ expectedSpan .Links ().RemoveIf (func (_ ptrace.SpanLink ) bool { return true })
837931 }
838932
839933 EnrichSpan (tc .input , config.Config {
840934 Span : tc .config ,
841935 })
842-
843- assert .Empty (t , cmp .Diff (expectedAttrs , tc .input .Attributes ().AsRaw ()))
936+ assert .NoError (t , ptracetest .CompareSpan (expectedSpan , tc .input ))
844937 })
845938 }
846939}
0 commit comments