diff --git a/exporters/otlp/internal/transform/span.go b/exporters/otlp/internal/transform/span.go index 38a48bf1d..ca67527cb 100644 --- a/exporters/otlp/internal/transform/span.go +++ b/exporters/otlp/internal/transform/span.go @@ -65,10 +65,10 @@ func span(sd *export.SpanData) *tracepb.Span { if sd == nil { return nil } - return &tracepb.Span{ + + s := &tracepb.Span{ TraceId: sd.SpanContext.TraceID[:], SpanId: sd.SpanContext.SpanID[:], - ParentSpanId: sd.ParentSpanID[:], Status: status(sd.StatusCode, sd.StatusMessage), StartTimeUnixNano: uint64(sd.StartTime.UnixNano()), EndTimeUnixNano: uint64(sd.EndTime.UnixNano()), @@ -82,6 +82,12 @@ func span(sd *export.SpanData) *tracepb.Span { DroppedEventsCount: uint32(sd.DroppedMessageEventCount), DroppedLinksCount: uint32(sd.DroppedLinkCount), } + + if sd.ParentSpanID.IsValid() { + s.ParentSpanId = sd.ParentSpanID[:] + } + + return s } // status transform a span code and message into an OTLP span status. diff --git a/exporters/otlp/internal/transform/span_test.go b/exporters/otlp/internal/transform/span_test.go index eec4b3c2f..9525e3e25 100644 --- a/exporters/otlp/internal/transform/span_test.go +++ b/exporters/otlp/internal/transform/span_test.go @@ -360,3 +360,12 @@ func TestSpanData(t *testing.T) { t.Fatalf("transformed span differs %v\n", diff) } } + +// Empty parent span ID should be treated as root span. +func TestRootSpanData(t *testing.T) { + rs := SpanData([]*export.SpanData{{}})[0] + got := rs.GetInstrumentationLibrarySpans()[0].GetSpans()[0].GetParentSpanId() + + // Empty means root span. + assert.Nil(t, got, "incorrect transform of root parent span ID") +}