Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recover the OT context header from the B3 headers if not propagated #1702

Merged
merged 5 commits into from
Sep 21, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
15 changes: 15 additions & 0 deletions source/common/tracing/zipkin/zipkin_tracer_impl.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "common/tracing/zipkin/zipkin_tracer_impl.h"

#include "common/common/enum_to_int.h"
#include "common/common/utility.h"
#include "common/http/headers.h"
#include "common/http/message_impl.h"
#include "common/http/utility.h"
Expand Down Expand Up @@ -105,6 +106,20 @@ Tracing::SpanPtr Driver::startSpan(const Tracing::Config& config, Http::HeaderMa
// annotation. In this case, we are dealing with an ingress operation. This envoy instance,
// being at the receiving end, will add the SR annotation to the shared span context.

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 traceId(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry didn't catch this before. Please use snake_case for variables (trace_id, span_id, etc.).

uint64_t spanId(0);
uint64_t parentId(0);
if (!StringUtil::atoul(request_headers.XB3TraceId()->value().c_str(), traceId, 16)
|| !StringUtil::atoul(request_headers.XB3SpanId()->value().c_str(), spanId, 16)
|| (request_headers.XB3ParentSpanId() && !StringUtil::atoul(request_headers.XB3ParentSpanId()->value().c_str(), parentId, 16))) {
return nullptr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd probably return nullspan here to be on a safe side.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry yes I meant NullSpan (not nullptr)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem will sort it tomorrow.

}

SpanContext context(traceId, spanId, parentId);

new_zipkin_span =
tracer.startSpan(config, request_headers.Host()->value().c_str(), start_time, context);
} else {
Expand Down
76 changes: 76 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,81 @@ 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());
}

TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidTraceIdB3HeadersTest) {
setupValidDriver();

request_headers_.insertXB3TraceId().value(std::string("xyz"));
request_headers_.insertXB3SpanId().value(Hex::uint64ToHex(Util::generateRandom64()));
request_headers_.insertXB3ParentSpanId().value(Hex::uint64ToHex(Util::generateRandom64()));

EXPECT_EQ(nullptr, driver_->startSpan(config_, request_headers_, operation_name_, start_time_));
}

TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidSpanIdB3HeadersTest) {
setupValidDriver();

request_headers_.insertXB3TraceId().value(Hex::uint64ToHex(Util::generateRandom64()));
request_headers_.insertXB3SpanId().value(std::string("xyz"));
request_headers_.insertXB3ParentSpanId().value(Hex::uint64ToHex(Util::generateRandom64()));

EXPECT_EQ(nullptr, driver_->startSpan(config_, request_headers_, operation_name_, start_time_));
}

TEST_F(ZipkinDriverTest, ZipkinSpanContextFromInvalidParentIdB3HeadersTest) {
setupValidDriver();

request_headers_.insertXB3TraceId().value(Hex::uint64ToHex(Util::generateRandom64()));
request_headers_.insertXB3SpanId().value(Hex::uint64ToHex(Util::generateRandom64()));
request_headers_.insertXB3ParentSpanId().value(std::string("xyz"));

EXPECT_EQ(nullptr, driver_->startSpan(config_, request_headers_, operation_name_, start_time_));
}
} // namespace Zipkin
} // namespace Envoy