Skip to content

Commit

Permalink
Recover the OT context header from the B3 headers if not propagated
Browse files Browse the repository at this point in the history
Resolves #1364

Signed-off-by: Gary Brown <[email protected]>
  • Loading branch information
objectiser committed Sep 20, 2017
1 parent d345261 commit e6b82ff
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
11 changes: 11 additions & 0 deletions source/common/tracing/zipkin/span_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ class SpanContext {
*/
SpanContext() : trace_id_(0), id_(0), parent_id_(0), is_initialized_(false) {}

/**
* Constructor that creates a context object from the supplied trace, span
* and parent ids.
*
* @param trace_id The trace id.
* @param id The span id.
* @param parent_id The parent id.
*/
SpanContext(const uint64_t trace_id, const uint64_t id, const uint64_t parent_id)
: trace_id_(trace_id), id_(id), parent_id_(parent_id), is_initialized_(true) {}

/**
* Constructor that creates a context object from the given Zipkin span object.
*
Expand Down
14 changes: 14 additions & 0 deletions source/common/tracing/zipkin/zipkin_tracer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,20 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, Http::HeaderMa

new_zipkin_span =
tracer.startSpan(config, request_headers.Host()->value().c_str(), start_time, context);

} else if (request_headers.XB3TraceId() && request_headers.XB3SpanId()) {
uint64_t parentId(0);
if (request_headers.XB3ParentSpanId()) {
parentId = std::stoull(request_headers.XB3ParentSpanId()->value().c_str(), nullptr, 16);
}

SpanContext context(std::stoull(request_headers.XB3TraceId()->value().c_str(), nullptr, 16),
std::stoull(request_headers.XB3SpanId()->value().c_str(), nullptr, 16),
parentId);

new_zipkin_span =
tracer.startSpan(config, request_headers.Host()->value().c_str(), start_time, context);

} else {
// Create a root Zipkin span. No context was found in the headers.
new_zipkin_span = tracer.startSpan(config, request_headers.Host()->value().c_str(), start_time);
Expand Down
46 changes: 46 additions & 0 deletions test/common/tracing/zipkin/zipkin_tracer_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -344,5 +344,51 @@ TEST_F(ZipkinDriverTest, ZipkinSpanTest) {
EXPECT_EQ("key3", zipkin_zipkin_span3.binaryAnnotations()[0].key());
EXPECT_EQ("value3", zipkin_zipkin_span3.binaryAnnotations()[0].value());
}

TEST_F(ZipkinDriverTest, ZipkinSpanContextFromOtSpanContextHeaderTest) {
setupValidDriver();

const std::string trace_id = Hex::uint64ToHex(Util::generateRandom64());
const std::string span_id = Hex::uint64ToHex(Util::generateRandom64());
const std::string parent_id = Hex::uint64ToHex(Util::generateRandom64());
const std::string context =
trace_id + ";" + span_id + ";" + parent_id + ";" + ZipkinCoreConstants::get().CLIENT_SEND;

request_headers_.insertOtSpanContext().value(context);

// New span will have an SR annotation - so its span and parent ids will be
// the same as the supplied span context (i.e. shared context)
Tracing::SpanPtr span =
driver_->startSpan(config_, request_headers_, operation_name_, start_time_);

ZipkinSpanPtr zipkin_span(dynamic_cast<ZipkinSpan*>(span.release()));

EXPECT_EQ(trace_id, zipkin_span->span().traceIdAsHexString());
EXPECT_EQ(span_id, zipkin_span->span().idAsHexString());
EXPECT_EQ(parent_id, zipkin_span->span().parentIdAsHexString());
}

TEST_F(ZipkinDriverTest, ZipkinSpanContextFromB3HeadersTest) {
setupValidDriver();

const std::string trace_id = Hex::uint64ToHex(Util::generateRandom64());
const std::string span_id = Hex::uint64ToHex(Util::generateRandom64());
const std::string parent_id = Hex::uint64ToHex(Util::generateRandom64());

request_headers_.insertXB3TraceId().value(trace_id);
request_headers_.insertXB3SpanId().value(span_id);
request_headers_.insertXB3ParentSpanId().value(parent_id);

// New span will have an SR annotation - so its span and parent ids will be
// the same as the supplied span context (i.e. shared context)
Tracing::SpanPtr span =
driver_->startSpan(config_, request_headers_, operation_name_, start_time_);

ZipkinSpanPtr zipkin_span(dynamic_cast<ZipkinSpan*>(span.release()));

EXPECT_EQ(trace_id, zipkin_span->span().traceIdAsHexString());
EXPECT_EQ(span_id, zipkin_span->span().idAsHexString());
EXPECT_EQ(parent_id, zipkin_span->span().parentIdAsHexString());
}
} // namespace Zipkin
} // namespace Envoy

0 comments on commit e6b82ff

Please sign in to comment.