Skip to content

Commit 2345a49

Browse files
committed
[receiver/awsxrayreceiver] fix span kind when translating segment with parent ID
1 parent 67157b2 commit 2345a49

File tree

3 files changed

+62
-8
lines changed

3 files changed

+62
-8
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"trace_id": "1-5f187253-6a106696d56b1f4ef9eba2ed",
3+
"id": "5cc4a447f5d4d696",
4+
"name": "segment",
5+
"start_time": 1595437651.680097,
6+
"parent_id": "bda182a644eee9b3"
7+
}

receiver/awsxrayreceiver/internal/translator/translator.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/hex"
88
"encoding/json"
99
"errors"
10+
"strings"
1011

1112
"go.opentelemetry.io/collector/pdata/pcommon"
1213
"go.opentelemetry.io/collector/pdata/ptrace"
@@ -65,7 +66,10 @@ func ToTraces(rawSeg []byte, recorder telemetry.Recorder) (ptrace.Traces, int, e
6566
// TraceID of the root segment in because embedded subsegments
6667
// do not have that information, but it's needed after we flatten
6768
// the embedded subsegment to generate independent child spans.
68-
_, err = segToSpans(seg, seg.TraceID, nil, spans)
69+
// Sometimes, subsegments are sent separately in an async workflow,
70+
// check segment type to determine the proper span kind.
71+
isSubsegment := seg.ParentID != nil && seg.Type != nil && strings.EqualFold(*seg.Type, "subsegment")
72+
_, err = segToSpans(seg, seg.TraceID, nil, isSubsegment, spans)
6973
if err != nil {
7074
recorder.RecordSegmentsRejected(count)
7175
return ptrace.Traces{}, count, err
@@ -74,18 +78,18 @@ func ToTraces(rawSeg []byte, recorder telemetry.Recorder) (ptrace.Traces, int, e
7478
return traceData, count, nil
7579
}
7680

77-
func segToSpans(seg awsxray.Segment, traceID, parentID *string, spans ptrace.SpanSlice) (ptrace.Span, error) {
81+
func segToSpans(seg awsxray.Segment, traceID, parentID *string, isSubsegment bool, spans ptrace.SpanSlice) (ptrace.Span, error) {
7882
span := spans.AppendEmpty()
7983

80-
err := populateSpan(&seg, traceID, parentID, span)
84+
err := populateSpan(&seg, traceID, parentID, isSubsegment, span)
8185
if err != nil {
8286
return ptrace.Span{}, err
8387
}
8488

8589
var populatedChildSpan ptrace.Span
8690
for _, s := range seg.Subsegments {
8791
populatedChildSpan, err = segToSpans(s,
88-
traceID, seg.ID,
92+
traceID, seg.ID, true
8993
spans)
9094
if err != nil {
9195
return ptrace.Span{}, err
@@ -109,7 +113,7 @@ func segToSpans(seg awsxray.Segment, traceID, parentID *string, spans ptrace.Spa
109113
return span, nil
110114
}
111115

112-
func populateSpan(seg *awsxray.Segment, traceID, parentID *string, span ptrace.Span) error {
116+
func populateSpan(seg *awsxray.Segment, traceID, parentID *string, isSubsegment bool, span ptrace.Span) error {
113117
attrs := span.Attributes()
114118
attrs.Clear()
115119
attrs.EnsureCapacity(initAttrCapacity)
@@ -156,11 +160,11 @@ func populateSpan(seg *awsxray.Segment, traceID, parentID *string, span ptrace.S
156160

157161
span.SetTraceID(traceIDBytes)
158162
span.SetSpanID(spanIDBytes)
159-
163+
if !isSubsegment {
164+
span.SetKind(ptrace.SpanKindServer)
165+
}
160166
if parentIDBytes != [8]byte{} {
161167
span.SetParentSpanID(parentIDBytes)
162-
} else {
163-
span.SetKind(ptrace.SpanKindServer)
164168
}
165169

166170
addStartTime(seg.StartTime, span)

receiver/awsxrayreceiver/internal/translator/translator_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,49 @@ func TestTranslation(t *testing.T) {
905905
assert.NoError(t, ptracetest.CompareResourceSpans(expectedRs, actualRs))
906906
},
907907
},
908+
{
909+
testCase: "TranslateSegmentWithParentId",
910+
samplePath: filepath.Join("../../../../internal/aws/xray", "testdata", "segmentWithParentId.txt"),
911+
expectedResourceAttrs: func(seg *awsxray.Segment) map[string]any {
912+
return map[string]any{
913+
string(conventions.ServiceNameKey): *seg.Name,
914+
string(conventions.CloudProviderKey): "unknown",
915+
}
916+
},
917+
expectedRecord: types.TelemetryRecord{
918+
SegmentsReceivedCount: aws.Int32(1),
919+
SegmentsRejectedCount: aws.Int32(0),
920+
},
921+
propsPerSpan: func(_ *testing.T, _ string, seg *awsxray.Segment) []perSpanProperties {
922+
attrs := pcommon.NewMap()
923+
res := perSpanProperties{
924+
traceID: *seg.TraceID,
925+
spanID: *seg.ID,
926+
parentSpanID: seg.ParentID,
927+
name: *seg.Name,
928+
startTimeSec: *seg.StartTime,
929+
endTimeSec: seg.EndTime,
930+
spanKind: ptrace.SpanKindServer,
931+
spanStatus: spanSt{
932+
code: ptrace.StatusCodeUnset,
933+
},
934+
attrs: attrs,
935+
}
936+
return []perSpanProperties{res}
937+
// return nil
938+
},
939+
verification: func(testCase string,
940+
_ *awsxray.Segment,
941+
expectedRs ptrace.ResourceSpans, actualTraces ptrace.Traces, err error,
942+
) {
943+
assert.NoError(t, err, testCase+": translation should've succeeded")
944+
assert.Equal(t, 1, actualTraces.ResourceSpans().Len(),
945+
testCase+": one segment should translate to 1 ResourceSpans")
946+
947+
actualRs := actualTraces.ResourceSpans().At(0)
948+
assert.NoError(t, ptracetest.CompareResourceSpans(expectedRs, actualRs))
949+
},
950+
},
908951
{
909952
testCase: "TranslateJsonUnmarshallFailed",
910953
expectedUnmarshallFailure: true,

0 commit comments

Comments
 (0)