From 9603803f31952483952eed948be1613205d6ee57 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Thu, 1 Aug 2019 14:43:45 +1000 Subject: [PATCH 1/7] tracing: Add B3 support in OpenCensus driver. This makes it possible to propagate, generate, and translate B3-format trace context headers. Signed-off-by: Emil Mikulic --- api/envoy/config/trace/v2/trace.proto | 3 + bazel/repositories.bzl | 4 + bazel/repository_locations.bzl | 7 +- source/extensions/tracers/opencensus/BUILD | 1 + .../opencensus/opencensus_tracer_impl.cc | 53 ++++++- .../tracers/opencensus/config_test.cc | 1 + .../tracers/opencensus/tracer_test.cc | 149 ++++++++++-------- 7 files changed, 142 insertions(+), 76 deletions(-) diff --git a/api/envoy/config/trace/v2/trace.proto b/api/envoy/config/trace/v2/trace.proto index 3fe4d1fff66f1..62ed0f439aee2 100644 --- a/api/envoy/config/trace/v2/trace.proto +++ b/api/envoy/config/trace/v2/trace.proto @@ -144,6 +144,9 @@ message OpenCensusConfig { // "X-Cloud-Trace-Context:" header. CLOUD_TRACE_CONTEXT = 3; + + // X-B3-* headers. + B3 = 4; } // List of incoming trace context headers we will accept. First one found diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 9cb20ae5f0a3c..c0b2205e0ad6c 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -528,6 +528,10 @@ def _io_opencensus_cpp(): name = "opencensus_trace", actual = "@io_opencensus_cpp//opencensus/trace", ) + native.bind( + name = "opencensus_trace_b3", + actual = "@io_opencensus_cpp//opencensus/trace:b3", + ) native.bind( name = "opencensus_trace_cloud_trace_context", actual = "@io_opencensus_cpp//opencensus/trace:cloud_trace_context", diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 1335ae70623b5..539c4f4ada771 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -233,9 +233,10 @@ REPOSITORY_LOCATIONS = dict( urls = ["https://files.pythonhosted.org/packages/b3/b2/238e2590826bfdd113244a40d9d3eb26918bd798fc187e2360a8367068db/six-1.10.0.tar.gz"], ), io_opencensus_cpp = dict( - sha256 = "9223b4d54af4151910dede03aa58247e90df72167fcc91d5f75e73a141568036", - strip_prefix = "opencensus-cpp-e292a374fb42c6cb2743f1689234bd409f4fda20", - urls = ["https://github.com/census-instrumentation/opencensus-cpp/archive/e292a374fb42c6cb2743f1689234bd409f4fda20.tar.gz"], + sha256 = "8d6016e47c2e19e7acbadb6f905b8c422748c64299d71101ac8f28151677e195", + strip_prefix = "opencensus-cpp-cad0d03ff3474cf14389fc249e16847ab7b6895f", + # 2019-07-31 + urls = ["https://github.com/census-instrumentation/opencensus-cpp/archive/cad0d03ff3474cf14389fc249e16847ab7b6895f.tar.gz"], ), com_github_curl = dict( sha256 = "821aeb78421375f70e55381c9ad2474bf279fc454b791b7e95fc83562951c690", diff --git a/source/extensions/tracers/opencensus/BUILD b/source/extensions/tracers/opencensus/BUILD index 90bc4f9fc7ed9..09224b9e2f23f 100644 --- a/source/extensions/tracers/opencensus/BUILD +++ b/source/extensions/tracers/opencensus/BUILD @@ -27,6 +27,7 @@ envoy_cc_library( hdrs = ["opencensus_tracer_impl.h"], external_deps = [ "opencensus_trace", + "opencensus_trace_b3", "opencensus_trace_cloud_trace_context", "opencensus_trace_grpc_trace_bin", "opencensus_trace_trace_context", diff --git a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc index 154e5903fe83b..83a5d4f5bd9b1 100644 --- a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc +++ b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc @@ -8,6 +8,7 @@ #include "opencensus/exporters/trace/stackdriver/stackdriver_exporter.h" #include "opencensus/exporters/trace/stdout/stdout_exporter.h" #include "opencensus/exporters/trace/zipkin/zipkin_exporter.h" +#include "opencensus/trace/propagation/b3.h" #include "opencensus/trace/propagation/cloud_trace_context.h" #include "opencensus/trace/propagation/grpc_trace_bin.h" #include "opencensus/trace/propagation/trace_context.h" @@ -29,6 +30,10 @@ class ConstantValues { const Http::LowerCaseString TRACEPARENT{"traceparent"}; const Http::LowerCaseString GRPC_TRACE_BIN{"grpc-trace-bin"}; const Http::LowerCaseString X_CLOUD_TRACE_CONTEXT{"x-cloud-trace-context"}; + const Http::LowerCaseString X_B3_TRACEID{"x-b3-traceid"}; + const Http::LowerCaseString X_B3_SPANID{"x-b3-spanid"}; + const Http::LowerCaseString X_B3_SAMPLED{"x-b3-sampled"}; + const Http::LowerCaseString X_B3_FLAGS{"x-b3-flags"}; }; using Constants = ConstSingleton; @@ -98,6 +103,35 @@ startSpanHelper(const std::string& name, bool traced, const Http::HeaderMap& req } break; } + + case OpenCensusConfig::B3: { + absl::string_view b3_trace_id; + absl::string_view b3_span_id; + absl::string_view b3_sampled; + absl::string_view b3_flags; + const Http::HeaderEntry* h_b3_trace_id = request_headers.get(Constants::get().X_B3_TRACEID); + if (h_b3_trace_id != nullptr) { + b3_trace_id = h_b3_trace_id->value().getStringView(); + } + const Http::HeaderEntry* h_b3_span_id = request_headers.get(Constants::get().X_B3_SPANID); + if (h_b3_span_id != nullptr) { + b3_span_id = h_b3_span_id->value().getStringView(); + } + const Http::HeaderEntry* h_b3_sampled = request_headers.get(Constants::get().X_B3_SAMPLED); + if (h_b3_sampled != nullptr) { + b3_sampled = h_b3_sampled->value().getStringView(); + } + const Http::HeaderEntry* h_b3_flags = request_headers.get(Constants::get().X_B3_FLAGS); + if (h_b3_flags != nullptr) { + b3_flags = h_b3_flags->value().getStringView(); + } + if (h_b3_trace_id != nullptr && h_b3_span_id != nullptr) { + found = true; + parent_ctx = ::opencensus::trace::propagation::FromB3Headers(b3_trace_id, b3_span_id, + b3_sampled, b3_flags); + } + break; + } } // First header found wins. if (found) { @@ -150,16 +184,16 @@ void Span::finishSpan() { span_.End(); } void Span::injectContext(Http::HeaderMap& request_headers) { using OpenCensusConfig = envoy::config::trace::v2::OpenCensusConfig; + const auto& ctx = span_.context(); for (const auto& outgoing : oc_config_.outgoing_trace_context()) { switch (outgoing) { case OpenCensusConfig::TRACE_CONTEXT: - request_headers.setReferenceKey( - Constants::get().TRACEPARENT, - ::opencensus::trace::propagation::ToTraceParentHeader(span_.context())); + request_headers.setReferenceKey(Constants::get().TRACEPARENT, + ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); break; case OpenCensusConfig::GRPC_TRACE_BIN: { - std::string val = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(span_.context()); + std::string val = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(ctx); val = Base64::encode(val.data(), val.size(), /*add_padding=*/false); request_headers.setReferenceKey(Constants::get().GRPC_TRACE_BIN, val); break; @@ -168,7 +202,16 @@ void Span::injectContext(Http::HeaderMap& request_headers) { case OpenCensusConfig::CLOUD_TRACE_CONTEXT: request_headers.setReferenceKey( Constants::get().X_CLOUD_TRACE_CONTEXT, - ::opencensus::trace::propagation::ToCloudTraceContextHeader(span_.context())); + ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); + break; + + case OpenCensusConfig::B3: + request_headers.setReferenceKey(Constants::get().X_B3_TRACEID, + ::opencensus::trace::propagation::ToB3TraceIdHeader(ctx)); + request_headers.setReferenceKey(Constants::get().X_B3_SPANID, + ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); + request_headers.setReferenceKey(Constants::get().X_B3_SAMPLED, + ::opencensus::trace::propagation::ToB3SampledHeader(ctx)); break; } } diff --git a/test/extensions/tracers/opencensus/config_test.cc b/test/extensions/tracers/opencensus/config_test.cc index 1f549cd4afb14..686f3e5b5813e 100644 --- a/test/extensions/tracers/opencensus/config_test.cc +++ b/test/extensions/tracers/opencensus/config_test.cc @@ -50,6 +50,7 @@ TEST(OpenCensusTracerConfigTest, OpenCensusHttpTracerWithTypedConfig) { stackdriver_project_id: test_project_id zipkin_exporter_enabled: true zipkin_url: http://127.0.0.1:9411/api/v2/spans + incoming_trace_context: b3 incoming_trace_context: trace_context incoming_trace_context: grpc_trace_bin incoming_trace_context: cloud_trace_context diff --git a/test/extensions/tracers/opencensus/tracer_test.cc b/test/extensions/tracers/opencensus/tracer_test.cc index 2c7cf5695fec6..d6e444b4e86bf 100644 --- a/test/extensions/tracers/opencensus/tracer_test.cc +++ b/test/extensions/tracers/opencensus/tracer_test.cc @@ -19,6 +19,7 @@ #include "gtest/gtest.h" #include "opencensus/trace/exporter/span_data.h" #include "opencensus/trace/exporter/span_exporter.h" +#include "opencensus/trace/propagation/b3.h" #include "opencensus/trace/propagation/cloud_trace_context.h" #include "opencensus/trace/propagation/grpc_trace_bin.h" #include "opencensus/trace/propagation/trace_context.h" @@ -165,74 +166,86 @@ TEST(OpenCensusTracerTest, Span) { TEST(OpenCensusTracerTest, PropagateTraceContext) { registerSpanCatcher(); // The test calls the helper with each kind of incoming context in turn. - auto helper = [](const std::string& header, const std::string& value) { - OpenCensusConfig oc_config; - NiceMock local_info; - oc_config.add_incoming_trace_context(OpenCensusConfig::NONE); - oc_config.add_incoming_trace_context(OpenCensusConfig::TRACE_CONTEXT); - oc_config.add_incoming_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); - oc_config.add_incoming_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); - oc_config.add_outgoing_trace_context(OpenCensusConfig::NONE); - oc_config.add_outgoing_trace_context(OpenCensusConfig::TRACE_CONTEXT); - oc_config.add_outgoing_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); - oc_config.add_outgoing_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); - std::unique_ptr driver(new OpenCensus::Driver(oc_config, local_info)); - NiceMock config; - Http::TestHeaderMapImpl request_headers{ - {":path", "/"}, - {":method", "GET"}, - {"x-request-id", "foo"}, - {header, value}, - }; - const std::string operation_name{"my_operation_2"}; - SystemTime start_time; - Http::TestHeaderMapImpl injected_headers; - { - Tracing::SpanPtr span = driver->startSpan(config, request_headers, operation_name, start_time, - {Tracing::Reason::Sampling, false}); - span->injectContext(injected_headers); - span->finishSpan(); - } - - // Retrieve SpanData from the OpenCensus trace exporter. - std::vector spans = getSpanCatcher()->catchSpans(); - ASSERT_EQ(1, spans.size()); - const auto& sd = spans[0]; - ENVOY_LOG_MISC(debug, "{}", sd.DebugString()); - - // Check contents. - EXPECT_TRUE(sd.has_remote_parent()); - EXPECT_EQ("6162636465666768", sd.parent_span_id().ToHex()); - EXPECT_EQ("404142434445464748494a4b4c4d4e4f", sd.context().trace_id().ToHex()); - EXPECT_TRUE(sd.context().trace_options().IsSampled()) - << "parent was sampled, child should be also"; - - // Check injectContext. - using Envoy::Http::LowerCaseString; - { - auto val = injected_headers.get(LowerCaseString("traceparent")); - ASSERT_NE(nullptr, val); - EXPECT_EQ(::opencensus::trace::propagation::ToTraceParentHeader(sd.context()), - val->value().getStringView()); - } - { - auto val = injected_headers.get(LowerCaseString("grpc-trace-bin")); - ASSERT_NE(nullptr, val); - std::string expected = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(sd.context()); - expected = Base64::encode(expected.data(), expected.size(), /*add_padding=*/false); - EXPECT_EQ(expected, val->value().getStringView()); - } - { - auto val = injected_headers.get(LowerCaseString("x-cloud-trace-context")); - ASSERT_NE(nullptr, val); - EXPECT_EQ(::opencensus::trace::propagation::ToCloudTraceContextHeader(sd.context()), - val->value().getStringView()); - } - }; - - helper("traceparent", "00-404142434445464748494a4b4c4d4e4f-6162636465666768-01"); - helper("grpc-trace-bin", "AABAQUJDREVGR0hJSktMTU5PAWFiY2RlZmdoAgE"); - helper("x-cloud-trace-context", "404142434445464748494a4b4c4d4e4f/7017280452245743464;o=1"); + auto test_incoming = + [](const std::initializer_list>& headers) { + using Envoy::Http::LowerCaseString; + OpenCensusConfig oc_config; + NiceMock local_info; + oc_config.add_incoming_trace_context(OpenCensusConfig::NONE); + oc_config.add_incoming_trace_context(OpenCensusConfig::B3); + oc_config.add_incoming_trace_context(OpenCensusConfig::TRACE_CONTEXT); + oc_config.add_incoming_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); + oc_config.add_incoming_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); + oc_config.add_outgoing_trace_context(OpenCensusConfig::NONE); + oc_config.add_outgoing_trace_context(OpenCensusConfig::B3); + oc_config.add_outgoing_trace_context(OpenCensusConfig::TRACE_CONTEXT); + oc_config.add_outgoing_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); + oc_config.add_outgoing_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); + std::unique_ptr driver(new OpenCensus::Driver(oc_config, local_info)); + NiceMock config; + Http::TestHeaderMapImpl request_headers{ + {":path", "/"}, + {":method", "GET"}, + {"x-request-id", "foo"}, + }; + for (const auto& kv : headers) { + request_headers.addCopy(LowerCaseString(kv.first), kv.second); + } + + const std::string operation_name{"my_operation_2"}; + SystemTime start_time; + Http::TestHeaderMapImpl injected_headers; + { + Tracing::SpanPtr span = driver->startSpan(config, request_headers, operation_name, + start_time, {Tracing::Reason::Sampling, false}); + span->injectContext(injected_headers); + span->finishSpan(); + } + + // Retrieve SpanData from the OpenCensus trace exporter. + std::vector spans = getSpanCatcher()->catchSpans(); + ASSERT_EQ(1, spans.size()); + const auto& sd = spans[0]; + ENVOY_LOG_MISC(debug, "{}", sd.DebugString()); + + // Check contents. + EXPECT_TRUE(sd.has_remote_parent()); + EXPECT_EQ("6162636465666768", sd.parent_span_id().ToHex()); + EXPECT_EQ("404142434445464748494a4b4c4d4e4f", sd.context().trace_id().ToHex()); + EXPECT_TRUE(sd.context().trace_options().IsSampled()) + << "parent was sampled, child should be also"; + + // Check injectContext. + // The SpanID is unpredictable so re-serialize context to check it. + const auto& ctx = sd.context(); + auto test_outgoing = [&injected_headers](const char* header, std::string expected_value) { + auto val = injected_headers.get(LowerCaseString(header)); + ASSERT_NE(nullptr, val); + EXPECT_EQ(expected_value, val->value().getStringView()); + }; + test_outgoing("traceparent", ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); + { + std::string expected = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(ctx); + expected = Base64::encode(expected.data(), expected.size(), /*add_padding=*/false); + test_outgoing("grpc-trace-bin", expected); + } + test_outgoing("x-cloud-trace-context", + ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); + test_outgoing("x-b3-traceid", "404142434445464748494a4b4c4d4e4f"); + test_outgoing("x-b3-spanid", ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); + test_outgoing("x-b3-sampled", "1"); + }; + + test_incoming({{"traceparent", "00-404142434445464748494a4b4c4d4e4f-6162636465666768-01"}}); + test_incoming({{"grpc-trace-bin", "AABAQUJDREVGR0hJSktMTU5PAWFiY2RlZmdoAgE"}}); + test_incoming( + {{"x-cloud-trace-context", "404142434445464748494a4b4c4d4e4f/7017280452245743464;o=1"}}); + test_incoming({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, + {"x-b3-spanid", "6162636465666768"}, + {"x-b3-sampled", "1"}}); + test_incoming({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, + {"x-b3-spanid", "6162636465666768"}, + {"x-b3-flags", "1"}}); // Debug flag causes sampling. } namespace { From c5c53fa996ec569f339bb0366da685f786565e2d Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Thu, 1 Aug 2019 14:48:27 +1000 Subject: [PATCH 2/7] Don't error on unused-parameter warnings. These come from tracing.grpc.pb.h which is autogenerated by the protobuf compiler. Signed-off-by: Emil Mikulic --- source/extensions/tracers/opencensus/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/source/extensions/tracers/opencensus/BUILD b/source/extensions/tracers/opencensus/BUILD index 09224b9e2f23f..492648fdf0883 100644 --- a/source/extensions/tracers/opencensus/BUILD +++ b/source/extensions/tracers/opencensus/BUILD @@ -25,6 +25,7 @@ envoy_cc_library( name = "opencensus_tracer_impl", srcs = ["opencensus_tracer_impl.cc"], hdrs = ["opencensus_tracer_impl.h"], + copts = ["-Wno-unused-parameter"], external_deps = [ "opencensus_trace", "opencensus_trace_b3", From 01ba65716c8947256934cf44847a959e7112a062 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Thu, 1 Aug 2019 19:03:49 +1000 Subject: [PATCH 3/7] Don't use deprecated API. Signed-off-by: Emil Mikulic --- source/extensions/tracers/opencensus/opencensus_tracer_impl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc index 83a5d4f5bd9b1..9f42500b62979 100644 --- a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc +++ b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc @@ -240,7 +240,7 @@ Driver::Driver(const envoy::config::trace::v2::OpenCensusConfig& oc_config, if (oc_config.stackdriver_exporter_enabled()) { ::opencensus::exporters::trace::StackdriverOptions opts; opts.project_id = oc_config.stackdriver_project_id(); - ::opencensus::exporters::trace::StackdriverExporter::Register(opts); + ::opencensus::exporters::trace::StackdriverExporter::Register(std::move(opts)); } if (oc_config.zipkin_exporter_enabled()) { ::opencensus::exporters::trace::ZipkinExporterOptions opts(oc_config.zipkin_url()); From a5d21666ccbba8e92c3331f6c1baa96b32ab9eb0 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Wed, 7 Aug 2019 15:52:19 +1000 Subject: [PATCH 4/7] Split PropagateTraceContext into per-header tests. Signed-off-by: Emil Mikulic --- .../tracers/opencensus/tracer_test.cc | 179 ++++++++++-------- 1 file changed, 97 insertions(+), 82 deletions(-) diff --git a/test/extensions/tracers/opencensus/tracer_test.cc b/test/extensions/tracers/opencensus/tracer_test.cc index d6e444b4e86bf..0bcedd1b97880 100644 --- a/test/extensions/tracers/opencensus/tracer_test.cc +++ b/test/extensions/tracers/opencensus/tracer_test.cc @@ -162,90 +162,105 @@ TEST(OpenCensusTracerTest, Span) { } } -// Test that trace context propagation works. -TEST(OpenCensusTracerTest, PropagateTraceContext) { +namespace { + +// Given incoming headers, test that trace context propagation works and generates all the expected +// outgoing headers. +void TestIncomingHeaders( + const std::initializer_list>& headers) { + using Envoy::Http::LowerCaseString; registerSpanCatcher(); - // The test calls the helper with each kind of incoming context in turn. - auto test_incoming = - [](const std::initializer_list>& headers) { - using Envoy::Http::LowerCaseString; - OpenCensusConfig oc_config; - NiceMock local_info; - oc_config.add_incoming_trace_context(OpenCensusConfig::NONE); - oc_config.add_incoming_trace_context(OpenCensusConfig::B3); - oc_config.add_incoming_trace_context(OpenCensusConfig::TRACE_CONTEXT); - oc_config.add_incoming_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); - oc_config.add_incoming_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); - oc_config.add_outgoing_trace_context(OpenCensusConfig::NONE); - oc_config.add_outgoing_trace_context(OpenCensusConfig::B3); - oc_config.add_outgoing_trace_context(OpenCensusConfig::TRACE_CONTEXT); - oc_config.add_outgoing_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); - oc_config.add_outgoing_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); - std::unique_ptr driver(new OpenCensus::Driver(oc_config, local_info)); - NiceMock config; - Http::TestHeaderMapImpl request_headers{ - {":path", "/"}, - {":method", "GET"}, - {"x-request-id", "foo"}, - }; - for (const auto& kv : headers) { - request_headers.addCopy(LowerCaseString(kv.first), kv.second); - } - - const std::string operation_name{"my_operation_2"}; - SystemTime start_time; - Http::TestHeaderMapImpl injected_headers; - { - Tracing::SpanPtr span = driver->startSpan(config, request_headers, operation_name, - start_time, {Tracing::Reason::Sampling, false}); - span->injectContext(injected_headers); - span->finishSpan(); - } - - // Retrieve SpanData from the OpenCensus trace exporter. - std::vector spans = getSpanCatcher()->catchSpans(); - ASSERT_EQ(1, spans.size()); - const auto& sd = spans[0]; - ENVOY_LOG_MISC(debug, "{}", sd.DebugString()); - - // Check contents. - EXPECT_TRUE(sd.has_remote_parent()); - EXPECT_EQ("6162636465666768", sd.parent_span_id().ToHex()); - EXPECT_EQ("404142434445464748494a4b4c4d4e4f", sd.context().trace_id().ToHex()); - EXPECT_TRUE(sd.context().trace_options().IsSampled()) - << "parent was sampled, child should be also"; - - // Check injectContext. - // The SpanID is unpredictable so re-serialize context to check it. - const auto& ctx = sd.context(); - auto test_outgoing = [&injected_headers](const char* header, std::string expected_value) { - auto val = injected_headers.get(LowerCaseString(header)); - ASSERT_NE(nullptr, val); - EXPECT_EQ(expected_value, val->value().getStringView()); - }; - test_outgoing("traceparent", ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); - { - std::string expected = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(ctx); - expected = Base64::encode(expected.data(), expected.size(), /*add_padding=*/false); - test_outgoing("grpc-trace-bin", expected); - } - test_outgoing("x-cloud-trace-context", - ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); - test_outgoing("x-b3-traceid", "404142434445464748494a4b4c4d4e4f"); - test_outgoing("x-b3-spanid", ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); - test_outgoing("x-b3-sampled", "1"); - }; - - test_incoming({{"traceparent", "00-404142434445464748494a4b4c4d4e4f-6162636465666768-01"}}); - test_incoming({{"grpc-trace-bin", "AABAQUJDREVGR0hJSktMTU5PAWFiY2RlZmdoAgE"}}); - test_incoming( + OpenCensusConfig oc_config; + NiceMock local_info; + oc_config.add_incoming_trace_context(OpenCensusConfig::NONE); + oc_config.add_incoming_trace_context(OpenCensusConfig::B3); + oc_config.add_incoming_trace_context(OpenCensusConfig::TRACE_CONTEXT); + oc_config.add_incoming_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); + oc_config.add_incoming_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); + oc_config.add_outgoing_trace_context(OpenCensusConfig::NONE); + oc_config.add_outgoing_trace_context(OpenCensusConfig::B3); + oc_config.add_outgoing_trace_context(OpenCensusConfig::TRACE_CONTEXT); + oc_config.add_outgoing_trace_context(OpenCensusConfig::GRPC_TRACE_BIN); + oc_config.add_outgoing_trace_context(OpenCensusConfig::CLOUD_TRACE_CONTEXT); + std::unique_ptr driver(new OpenCensus::Driver(oc_config, local_info)); + NiceMock config; + Http::TestHeaderMapImpl request_headers{ + {":path", "/"}, + {":method", "GET"}, + {"x-request-id", "foo"}, + }; + for (const auto& kv : headers) { + request_headers.addCopy(LowerCaseString(kv.first), kv.second); + } + + const std::string operation_name{"my_operation_2"}; + SystemTime start_time; + Http::TestHeaderMapImpl injected_headers; + { + Tracing::SpanPtr span = driver->startSpan(config, request_headers, operation_name, start_time, + {Tracing::Reason::Sampling, false}); + span->injectContext(injected_headers); + span->finishSpan(); + } + + // Retrieve SpanData from the OpenCensus trace exporter. + std::vector spans = getSpanCatcher()->catchSpans(); + ASSERT_EQ(1, spans.size()); + const auto& sd = spans[0]; + ENVOY_LOG_MISC(debug, "{}", sd.DebugString()); + + // Check contents. + EXPECT_TRUE(sd.has_remote_parent()); + EXPECT_EQ("6162636465666768", sd.parent_span_id().ToHex()); + EXPECT_EQ("404142434445464748494a4b4c4d4e4f", sd.context().trace_id().ToHex()); + EXPECT_TRUE(sd.context().trace_options().IsSampled()) + << "parent was sampled, child should be also"; + + // Check injectContext. + // The SpanID is unpredictable so re-serialize context to check it. + const auto& ctx = sd.context(); + auto test_outgoing = [&injected_headers](const char* header, std::string expected_value) { + auto val = injected_headers.get(LowerCaseString(header)); + ASSERT_NE(nullptr, val); + EXPECT_EQ(expected_value, val->value().getStringView()); + }; + test_outgoing("traceparent", ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); + { + std::string expected = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(ctx); + expected = Base64::encode(expected.data(), expected.size(), /*add_padding=*/false); + test_outgoing("grpc-trace-bin", expected); + } + test_outgoing("x-cloud-trace-context", + ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); + test_outgoing("x-b3-traceid", "404142434445464748494a4b4c4d4e4f"); + test_outgoing("x-b3-spanid", ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); + test_outgoing("x-b3-sampled", "1"); +} +} // namespace + +TEST(OpenCensusTracerTest, PropagateTraceParentContext) { + TestIncomingHeaders({{"traceparent", "00-404142434445464748494a4b4c4d4e4f-6162636465666768-01"}}); +} + +TEST(OpenCensusTracerTest, PropagateGrpcTraceBinContext) { + TestIncomingHeaders({{"grpc-trace-bin", "AABAQUJDREVGR0hJSktMTU5PAWFiY2RlZmdoAgE"}}); +} + +TEST(OpenCensusTracerTest, PropagateCloudTraceContext) { + TestIncomingHeaders( {{"x-cloud-trace-context", "404142434445464748494a4b4c4d4e4f/7017280452245743464;o=1"}}); - test_incoming({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, - {"x-b3-spanid", "6162636465666768"}, - {"x-b3-sampled", "1"}}); - test_incoming({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, - {"x-b3-spanid", "6162636465666768"}, - {"x-b3-flags", "1"}}); // Debug flag causes sampling. +} + +TEST(OpenCensusTracerTest, PropagateB3Context) { + TestIncomingHeaders({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, + {"x-b3-spanid", "6162636465666768"}, + {"x-b3-sampled", "1"}}); +} + +TEST(OpenCensusTracerTest, PropagateB3ContextWithDebugFlag) { + TestIncomingHeaders({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, + {"x-b3-spanid", "6162636465666768"}, + {"x-b3-flags", "1"}}); // Debug flag causes sampling. } namespace { From 4e4f455f961f4c25354925e68cc8e36bc85efd17 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Wed, 7 Aug 2019 15:52:33 +1000 Subject: [PATCH 5/7] Add comment about X-B3-Flags. Signed-off-by: Emil Mikulic --- source/extensions/tracers/opencensus/opencensus_tracer_impl.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc index a6ce09b743278..9be9d34848684 100644 --- a/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc +++ b/source/extensions/tracers/opencensus/opencensus_tracer_impl.cc @@ -215,6 +215,8 @@ void Span::injectContext(Http::HeaderMap& request_headers) { ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); request_headers.setReferenceKey(Constants::get().X_B3_SAMPLED, ::opencensus::trace::propagation::ToB3SampledHeader(ctx)); + // OpenCensus's trace context propagation doesn't produce the + // "X-B3-Flags:" header. break; } } From 914a9532684cc1caaab5ebd5847c7ae1a0d36e69 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Wed, 7 Aug 2019 16:06:28 +1000 Subject: [PATCH 6/7] Change test_outgoing helper to gunit MATCHER. Signed-off-by: Emil Mikulic --- .../tracers/opencensus/tracer_test.cc | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/test/extensions/tracers/opencensus/tracer_test.cc b/test/extensions/tracers/opencensus/tracer_test.cc index 0bcedd1b97880..d2a0cb3e69a5d 100644 --- a/test/extensions/tracers/opencensus/tracer_test.cc +++ b/test/extensions/tracers/opencensus/tracer_test.cc @@ -164,11 +164,22 @@ TEST(OpenCensusTracerTest, Span) { namespace { +using testing::PrintToString; + +MATCHER_P2(ContainHeader, header, expected_value, + "contains the header " + PrintToString(header) + " with value " + + PrintToString(expected_value)) { + auto found_value = arg.get(Http::LowerCaseString(header)); + if (found_value == nullptr) { + return false; + } + return found_value->value().getStringView() == expected_value; +} + // Given incoming headers, test that trace context propagation works and generates all the expected // outgoing headers. void TestIncomingHeaders( const std::initializer_list>& headers) { - using Envoy::Http::LowerCaseString; registerSpanCatcher(); OpenCensusConfig oc_config; NiceMock local_info; @@ -190,7 +201,7 @@ void TestIncomingHeaders( {"x-request-id", "foo"}, }; for (const auto& kv : headers) { - request_headers.addCopy(LowerCaseString(kv.first), kv.second); + request_headers.addCopy(Http::LowerCaseString(kv.first), kv.second); } const std::string operation_name{"my_operation_2"}; @@ -219,22 +230,21 @@ void TestIncomingHeaders( // Check injectContext. // The SpanID is unpredictable so re-serialize context to check it. const auto& ctx = sd.context(); - auto test_outgoing = [&injected_headers](const char* header, std::string expected_value) { - auto val = injected_headers.get(LowerCaseString(header)); - ASSERT_NE(nullptr, val); - EXPECT_EQ(expected_value, val->value().getStringView()); - }; - test_outgoing("traceparent", ::opencensus::trace::propagation::ToTraceParentHeader(ctx)); + const auto& hdrs = injected_headers; + EXPECT_THAT(hdrs, ContainHeader("traceparent", + ::opencensus::trace::propagation::ToTraceParentHeader(ctx))); { std::string expected = ::opencensus::trace::propagation::ToGrpcTraceBinHeader(ctx); expected = Base64::encode(expected.data(), expected.size(), /*add_padding=*/false); - test_outgoing("grpc-trace-bin", expected); + EXPECT_THAT(hdrs, ContainHeader("grpc-trace-bin", expected)); } - test_outgoing("x-cloud-trace-context", - ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx)); - test_outgoing("x-b3-traceid", "404142434445464748494a4b4c4d4e4f"); - test_outgoing("x-b3-spanid", ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx)); - test_outgoing("x-b3-sampled", "1"); + EXPECT_THAT(hdrs, + ContainHeader("x-cloud-trace-context", + ::opencensus::trace::propagation::ToCloudTraceContextHeader(ctx))); + EXPECT_THAT(hdrs, ContainHeader("x-b3-traceid", "404142434445464748494a4b4c4d4e4f")); + EXPECT_THAT( + hdrs, ContainHeader("x-b3-spanid", ::opencensus::trace::propagation::ToB3SpanIdHeader(ctx))); + EXPECT_THAT(hdrs, ContainHeader("x-b3-sampled", "1")); } } // namespace From 16d1ddc3dfca6095f7acede109538296be4b248e Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Thu, 8 Aug 2019 11:35:23 +1000 Subject: [PATCH 7/7] Fix nits. Signed-off-by: Emil Mikulic --- test/extensions/tracers/opencensus/tracer_test.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/extensions/tracers/opencensus/tracer_test.cc b/test/extensions/tracers/opencensus/tracer_test.cc index d2a0cb3e69a5d..241f1d0a9a895 100644 --- a/test/extensions/tracers/opencensus/tracer_test.cc +++ b/test/extensions/tracers/opencensus/tracer_test.cc @@ -169,7 +169,7 @@ using testing::PrintToString; MATCHER_P2(ContainHeader, header, expected_value, "contains the header " + PrintToString(header) + " with value " + PrintToString(expected_value)) { - auto found_value = arg.get(Http::LowerCaseString(header)); + const auto found_value = arg.get(Http::LowerCaseString(header)); if (found_value == nullptr) { return false; } @@ -178,7 +178,7 @@ MATCHER_P2(ContainHeader, header, expected_value, // Given incoming headers, test that trace context propagation works and generates all the expected // outgoing headers. -void TestIncomingHeaders( +void testIncomingHeaders( const std::initializer_list>& headers) { registerSpanCatcher(); OpenCensusConfig oc_config; @@ -249,26 +249,26 @@ void TestIncomingHeaders( } // namespace TEST(OpenCensusTracerTest, PropagateTraceParentContext) { - TestIncomingHeaders({{"traceparent", "00-404142434445464748494a4b4c4d4e4f-6162636465666768-01"}}); + testIncomingHeaders({{"traceparent", "00-404142434445464748494a4b4c4d4e4f-6162636465666768-01"}}); } TEST(OpenCensusTracerTest, PropagateGrpcTraceBinContext) { - TestIncomingHeaders({{"grpc-trace-bin", "AABAQUJDREVGR0hJSktMTU5PAWFiY2RlZmdoAgE"}}); + testIncomingHeaders({{"grpc-trace-bin", "AABAQUJDREVGR0hJSktMTU5PAWFiY2RlZmdoAgE"}}); } TEST(OpenCensusTracerTest, PropagateCloudTraceContext) { - TestIncomingHeaders( + testIncomingHeaders( {{"x-cloud-trace-context", "404142434445464748494a4b4c4d4e4f/7017280452245743464;o=1"}}); } TEST(OpenCensusTracerTest, PropagateB3Context) { - TestIncomingHeaders({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, + testIncomingHeaders({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, {"x-b3-spanid", "6162636465666768"}, {"x-b3-sampled", "1"}}); } TEST(OpenCensusTracerTest, PropagateB3ContextWithDebugFlag) { - TestIncomingHeaders({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, + testIncomingHeaders({{"x-b3-traceid", "404142434445464748494a4b4c4d4e4f"}, {"x-b3-spanid", "6162636465666768"}, {"x-b3-flags", "1"}}); // Debug flag causes sampling. }