diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index d098ddea3b..327fc317ca 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -35,11 +35,15 @@ void Recordable::SetIdentity(const opentelemetry::trace::SpanContext &span_conte span_context.trace_id().ToLowerBase16(trace_id_lower_base16); char span_id_lower_base16[trace::SpanId::kSize * 2] = {0}; span_context.span_id().ToLowerBase16(span_id_lower_base16); - char parent_span_id_lower_base16[trace::SpanId::kSize * 2] = {0}; - parent_span_id.ToLowerBase16(parent_span_id_lower_base16); - span_["id"] = std::string(span_id_lower_base16, 16); - span_["parentId"] = std::string(parent_span_id_lower_base16, 16); - span_["traceId"] = std::string(trace_id_lower_base16, 32); + if (parent_span_id.IsValid()) + { + char parent_span_id_lower_base16[trace::SpanId::kSize * 2] = {0}; + parent_span_id.ToLowerBase16(parent_span_id_lower_base16); + span_["parentId"] = std::string(parent_span_id_lower_base16, 16); + } + + span_["id"] = std::string(span_id_lower_base16, 16); + span_["traceId"] = std::string(trace_id_lower_base16, 32); } void PopulateAttribute(nlohmann::json &attribute, diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index f16ac2ab7e..dd66a058eb 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -43,6 +43,29 @@ TEST(ZipkinSpanRecordable, SetIdentity) EXPECT_EQ(rec.span(), j_span); } +// according to https://zipkin.io/zipkin-api/#/ in case root span is created +// the parentId filed should be absent. +TEST(ZipkinSpanRecordable, SetIdentityEmptyParent) +{ + json j_span = {{"id", "0000000000000002"}, {"traceId", "00000000000000000000000000000001"}}; + opentelemetry::exporter::zipkin::Recordable rec; + const trace::TraceId trace_id(std::array( + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})); + + const trace::SpanId span_id( + std::array({0, 0, 0, 0, 0, 0, 0, 2})); + + const trace::SpanId parent_span_id( + std::array({0, 0, 0, 0, 0, 0, 0, 0})); + + const opentelemetry::trace::SpanContext span_context{ + trace_id, span_id, + opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, true}; + + rec.SetIdentity(span_context, parent_span_id); + EXPECT_EQ(rec.span(), j_span); +} + TEST(ZipkinSpanRecordable, SetName) { nostd::string_view name = "Test Span";