diff --git a/examples/App.cpp b/examples/App.cpp index f7df8a2a..10801f0e 100644 --- a/examples/App.cpp +++ b/examples/App.cpp @@ -24,6 +24,12 @@ void tracedSubroutine(const std::unique_ptr& parentSpan) void tracedFunction() { + //{ + //jaegertracing::SpanContext spanContextWithUserIDs { {111, 222}, 333, 0, 0, {} }; // TraceId and SpanID must be != 0 + //auto span = opentracing::Tracer::Global()->StartSpan( + // "tracedFunction1", {jaegertracing::SelfRef(&spanContextWithUserIDs)}); + //} + auto span = opentracing::Tracer::Global()->StartSpan("tracedFunction"); tracedSubroutine(span); } diff --git a/src/jaegertracing/Reference.h b/src/jaegertracing/Reference.h index 52277aea..8d8bff71 100644 --- a/src/jaegertracing/Reference.h +++ b/src/jaegertracing/Reference.h @@ -30,6 +30,9 @@ namespace thrift { class SpanRef; } +// An extension of enum opentracing::SpanReferenceType, for a new Span. Only to copy traceID and spanID +const static int SpanReferenceType_JaegerSpecific_SelfRef = 99; + class Reference { public: using Type = opentracing::SpanReferenceType; diff --git a/src/jaegertracing/Tracer.cpp b/src/jaegertracing/Tracer.cpp index 1fb6087a..58863e8a 100644 --- a/src/jaegertracing/Tracer.cpp +++ b/src/jaegertracing/Tracer.cpp @@ -67,6 +67,7 @@ Tracer::StartSpanWithOptions(string_view operationName, try { const auto result = analyzeReferences(options.references); const auto* parent = result._parent; + const auto* self = result._self; const auto& references = result._references; std::vector samplerTags; @@ -75,11 +76,19 @@ Tracer::StartSpanWithOptions(string_view operationName, if (!parent || !parent->isValid()) { newTrace = true; auto highID = static_cast(0); - if (_options & kGen128BitOption) { - highID = randomID(); + auto lowID = static_cast(0); + if (self) { + highID = self->traceID().high(); + lowID = self->traceID().low(); } - const TraceID traceID(highID, randomID()); - const auto spanID = traceID.low(); + else { + if (_options & kGen128BitOption) { + highID = randomID(); + } + lowID = randomID(); + } + const TraceID traceID(highID, lowID); + const auto spanID = self ? self->spanID() : traceID.low(); const auto parentID = 0; auto flags = static_cast(0); if (parent && parent->isDebugIDContainerOnly()) { @@ -101,7 +110,7 @@ Tracer::StartSpanWithOptions(string_view operationName, } else { const auto traceID = parent->traceID(); - const auto spanID = randomID(); + const auto spanID = self ? self->spanID() : randomID(); const auto parentID = parent->spanID(); const auto flags = parent->flags(); ctx = SpanContext(traceID, spanID, parentID, flags, StrMap()); @@ -194,6 +203,12 @@ Tracer::analyzeReferences(const std::vector& references) const continue; } + if (static_cast(ref.first) == SpanReferenceType_JaegerSpecific_SelfRef) + { + result._self = ctx; + continue; // not a reference + } + result._references.emplace_back(Reference(*ctx, ref.first)); if (!hasParent) { diff --git a/src/jaegertracing/Tracer.h b/src/jaegertracing/Tracer.h index b0619696..ecaa6a87 100644 --- a/src/jaegertracing/Tracer.h +++ b/src/jaegertracing/Tracer.h @@ -273,11 +273,13 @@ class Tracer : public opentracing::Tracer, struct AnalyzedReferences { AnalyzedReferences() : _parent(nullptr) + , _self(nullptr) , _references() { } const SpanContext* _parent; + const SpanContext* _self; std::vector _references; }; @@ -301,6 +303,14 @@ class Tracer : public opentracing::Tracer, int _options; }; + +// jaegertracing::SelfRef returns a StartSpanOption pointing to the Span which traceID and spanID should become the new Span's IDs +// +// See opentracing::SpanReference +inline opentracing::SpanReference SelfRef(const opentracing::SpanContext* span_context) noexcept { + return {static_cast(SpanReferenceType_JaegerSpecific_SelfRef), span_context}; +} + } // namespace jaegertracing #endif // JAEGERTRACING_TRACER_H diff --git a/src/jaegertracing/TracerTest.cpp b/src/jaegertracing/TracerTest.cpp index 4a5a0057..27cca66b 100644 --- a/src/jaegertracing/TracerTest.cpp +++ b/src/jaegertracing/TracerTest.cpp @@ -490,4 +490,18 @@ TEST(Tracer, testTracerTags) ASSERT_EQ(std::string("test-service"), jaegerTracer->serviceName()); } +TEST(Tracer, testTracerStartSpanSelfRef) +{ + const auto handle = testutils::TracerUtil::installGlobalTracer(); + const auto tracer = std::static_pointer_cast(opentracing::Tracer::Global()); + { + jaegertracing::SpanContext spanSelfContext { {1, 2}, 3, 0, 0, jaegertracing::SpanContext::StrMap() }; + auto span = tracer->StartSpan("tracedFunction1", {jaegertracing::SelfRef(&spanSelfContext)}); + auto jaegerSpan = dynamic_cast(*span.get()); + ASSERT_EQ(jaegerSpan.context().traceID(), jaegertracing::TraceID(1, 2)); + ASSERT_EQ(jaegerSpan.context().spanID(), 3); + } + tracer->Close(); +} + } // namespace jaegertracing