From 63a2526c149be34a62ba7cc79b4f3e27f33ac741 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Mon, 30 Nov 2020 14:26:29 +0100 Subject: [PATCH 01/10] Implemented W3C traceparent propagation Signed-off-by: Tobias Stadler --- src/jaegertracing/ConfigTest.cpp | 15 ++ src/jaegertracing/Constants.h.in | 1 + src/jaegertracing/SpanContext.cpp | 66 ++++++- src/jaegertracing/SpanContext.h | 33 +++- src/jaegertracing/SpanContextTest.cpp | 69 ++++++- src/jaegertracing/TraceID.cpp | 38 +++- src/jaegertracing/TraceID.h | 36 +++- src/jaegertracing/TraceIDTest.cpp | 29 ++- src/jaegertracing/TracerTest.cpp | 40 +++++ src/jaegertracing/propagation/Format.cpp | 18 ++ src/jaegertracing/propagation/Format.h | 28 +++ src/jaegertracing/propagation/HeadersConfig.h | 45 ++++- src/jaegertracing/propagation/Propagator.h | 6 +- src/jaegertracing/testutils/TracerUtil.cpp | 169 +++++++++--------- src/jaegertracing/testutils/TracerUtil.h | 4 + 15 files changed, 487 insertions(+), 110 deletions(-) create mode 100644 src/jaegertracing/propagation/Format.cpp create mode 100644 src/jaegertracing/propagation/Format.h diff --git a/src/jaegertracing/ConfigTest.cpp b/src/jaegertracing/ConfigTest.cpp index 225d8e31..6679735e 100644 --- a/src/jaegertracing/ConfigTest.cpp +++ b/src/jaegertracing/ConfigTest.cpp @@ -94,6 +94,21 @@ TEST(Config, testZeroSamplingParam) } } +TEST(Config, testW3CTraceContextHeaderFormat) +{ + { + constexpr auto kConfigYAML = R"cfg( +headers: + TraceContextHeaderFormat: W3C +)cfg"; + const auto config = Config::parse(YAML::Load(kConfigYAML)); + ASSERT_EQ(kW3CTraceContextHeaderName, + config.headers().traceContextHeaderName()); + ASSERT_EQ(propagation::Format::W3C, + config.headers().traceContextHeaderFormat()); + } +} + #endif // JAEGERTRACING_WITH_YAML_CPP TEST(Config, testFromEnv) diff --git a/src/jaegertracing/Constants.h.in b/src/jaegertracing/Constants.h.in index c5b90f55..2c316b70 100644 --- a/src/jaegertracing/Constants.h.in +++ b/src/jaegertracing/Constants.h.in @@ -31,6 +31,7 @@ static constexpr auto kSamplerTypeTagKey = "sampler.type"; static constexpr auto kSamplerParamTagKey = "sampler.param"; static constexpr auto kTraceContextHeaderName = "uber-trace-id"; static constexpr auto kTracerStateHeaderName = kTraceContextHeaderName; +static constexpr auto kW3CTraceContextHeaderName = "traceparent"; static constexpr auto kTraceBaggageHeaderPrefix = "uberctx-"; static constexpr auto kSamplerTypeConst = "const"; static constexpr auto kSamplerTypeRemote = "remote"; diff --git a/src/jaegertracing/SpanContext.cpp b/src/jaegertracing/SpanContext.cpp index effbf11a..67f74f00 100644 --- a/src/jaegertracing/SpanContext.cpp +++ b/src/jaegertracing/SpanContext.cpp @@ -20,7 +20,7 @@ namespace jaegertracing { -SpanContext SpanContext::fromStream(std::istream& in) +SpanContext SpanContext::parseJaegerFormat(std::istream& in) { SpanContext spanContext; spanContext._traceID = TraceID::fromStream(in); @@ -65,4 +65,68 @@ SpanContext SpanContext::fromStream(std::istream& in) return spanContext; } +SpanContext SpanContext::parseW3CFormat(std::istream& in) +{ + char ch = '\0'; + if (!in.get(ch) || ch != '0') { + return SpanContext(); + } + + if (!in.get(ch) || ch != '0') { + return SpanContext(); + } + + if (!in.get(ch) || ch != '-') { + return SpanContext(); + } + + SpanContext spanContext; + spanContext._traceID = TraceID::fromStream(in, PropagationFormat::W3C); + if (!spanContext._traceID.isValid()) { + return SpanContext(); + } + + if (!in.get(ch) || ch != '-') { + return SpanContext(); + } + + constexpr auto kMaxUInt64Chars = static_cast(16); + auto buffer = utils::HexParsing::readSegment(in, kMaxUInt64Chars, '-'); + if (buffer.empty()) { + return SpanContext(); + } + spanContext._spanID = utils::HexParsing::decodeHex(buffer); + + if (!in.get(ch) || ch != '-') { + return SpanContext(); + } + + constexpr auto kMaxByteChars = static_cast(2); + buffer = utils::HexParsing::readSegment(in, kMaxByteChars, '-'); + if (buffer.empty() || buffer.size() != 2) { + return SpanContext(); + } + spanContext._flags = utils::HexParsing::decodeHex(buffer); + + in.clear(); + return spanContext; +} + +SpanContext SpanContext::fromStream(std::istream& in, PropagationFormat format) +{ + switch (format) { + case PropagationFormat::JAEGER: + return parseJaegerFormat(in); + case PropagationFormat::W3C: + return parseW3CFormat(in); + } + + return SpanContext(); +} + +SpanContext SpanContext::fromStream(std::istream& in) +{ + return fromStream(in, PropagationFormat::JAEGER); +} + } // namespace jaegertracing diff --git a/src/jaegertracing/SpanContext.h b/src/jaegertracing/SpanContext.h index 295a7e91..dd4a5432 100644 --- a/src/jaegertracing/SpanContext.h +++ b/src/jaegertracing/SpanContext.h @@ -27,17 +27,19 @@ #include #include "jaegertracing/Compilers.h" - #include "jaegertracing/TraceID.h" +#include "jaegertracing/propagation/Format.h" namespace jaegertracing { class SpanContext : public opentracing::SpanContext { public: using StrMap = std::unordered_map; + using PropagationFormat = propagation::Format; enum class Flag : unsigned char { kSampled = 1, kDebug = 2 }; + static SpanContext fromStream(std::istream& in, PropagationFormat format); static SpanContext fromStream(std::istream& in); SpanContext() @@ -152,12 +154,32 @@ class SpanContext : public opentracing::SpanContext { bool isValid() const { return _traceID.isValid() && _spanID != 0; } + template + void print(Stream& out, PropagationFormat format) const + { + switch (format) { + case PropagationFormat::JAEGER: + _traceID.print(out, PropagationFormat::JAEGER); + out << ':' << std::hex << _spanID << ':' << std::hex << _parentID + << ':' << std::hex << static_cast(_flags); + break; + case PropagationFormat::W3C: + out << "00"; + out << '-'; + _traceID.print(out, PropagationFormat::W3C); + out << '-'; + out << std::setw(16) << std::setfill('0') << std::hex << _spanID; + out << '-'; + out << std::setw(2) << std::setfill('0') << std::hex + << static_cast(_flags); + break; + } + } + template void print(Stream& out) const { - _traceID.print(out); - out << ':' << std::hex << _spanID << ':' << std::hex << _parentID << ':' - << std::hex << static_cast(_flags); + print(out, PropagationFormat::JAEGER); } void ForeachBaggageItem( @@ -195,6 +217,9 @@ class SpanContext : public opentracing::SpanContext { } private: + static SpanContext parseJaegerFormat(std::istream& in); + static SpanContext parseW3CFormat(std::istream& in); + TraceID _traceID; uint64_t _spanID; uint64_t _parentID; diff --git a/src/jaegertracing/SpanContextTest.cpp b/src/jaegertracing/SpanContextTest.cpp index 6eef6b3c..f9d41e2f 100644 --- a/src/jaegertracing/SpanContextTest.cpp +++ b/src/jaegertracing/SpanContextTest.cpp @@ -24,6 +24,8 @@ namespace jaegertracing { namespace { +using PropagationFormat = propagation::Format; + struct FromStreamTestCase { std::string _input; bool _success; @@ -31,7 +33,7 @@ struct FromStreamTestCase { } // anonymous namespace -TEST(SpanContext, testFromStream) +TEST(SpanContext, testFromStreamWithJaegerFormat) { const FromStreamTestCase testCases[] = { { "", false }, @@ -57,7 +59,7 @@ TEST(SpanContext, testFromStream) { std::stringstream ss; ss << testCase._input; - spanContext = SpanContext::fromStream(ss); + spanContext = SpanContext::fromStream(ss, PropagationFormat::JAEGER); ASSERT_EQ(testCase._success, spanContext.isValid()) << "input=" << testCase._input; } @@ -73,12 +75,67 @@ TEST(SpanContext, testFromStream) } } -TEST(SpanContext, testFormatting) +TEST(SpanContext, testFromStreamWithW3CFormat) +{ + const FromStreamTestCase testCases[] = { + { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", true }, + { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-00", true }, + { "00-11111111111111111111111111111111-2222222222222222-01", true }, + { "00-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-BBBBBBBBBBBBBBBB-01", true }, + { "", false }, + { "000af7651916cd43dd8448eb211c80319cb9c7c989f97918e101", false }, + { "000af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319cb9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e101", false }, + { "000af7651916cd43dd8448eb211c80319cb9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319cb9c7c989f97918e101", false }, + { "01-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "000-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "0k-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "k0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "00-00000000000000000000000000000000-b9c7c989f97918e1-01", false }, + { "01-0af7651916cd43dd8448eb211c80319-b9c7c989f97918e1-01", false }, + { "01-0af7651916cd43dd8448eb211c80319cc-b9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01", false } + }; + + for (auto&& testCase : testCases) { + SpanContext spanContext; + { + std::stringstream ss; + ss << testCase._input; + spanContext = SpanContext::fromStream(ss, PropagationFormat::W3C); + ASSERT_EQ(testCase._success, spanContext.isValid()) + << "input=" << testCase._input; + } + } +} + +TEST(SpanContext, testJaegerFormatting) +{ + SpanContext spanContext(TraceID(255, 1), 2, 3, 1, SpanContext::StrMap()); + { + std::ostringstream oss; + spanContext.print(oss, PropagationFormat::JAEGER); + ASSERT_EQ("ff0000000000000001:2:3:1", oss.str()); + } + { + std::ostringstream oss; + oss << spanContext; + ASSERT_EQ("ff0000000000000001:2:3:1", oss.str()); + } +} + +TEST(SpanContext, testW3CFormatting) { - SpanContext spanContext(TraceID(255, 255), 0, 0, 0, SpanContext::StrMap()); + SpanContext spanContext(TraceID(255, 1), 2, 3, 1, SpanContext::StrMap()); std::ostringstream oss; - oss << spanContext; - ASSERT_EQ("ff00000000000000ff:0:0:0", oss.str()); + spanContext.print(oss, PropagationFormat::W3C); + ASSERT_EQ("00-00000000000000ff0000000000000001-0000000000000002-01", + oss.str()); } TEST(SpanContext, testBaggage) diff --git a/src/jaegertracing/TraceID.cpp b/src/jaegertracing/TraceID.cpp index 59a5ceb4..107aaeb6 100644 --- a/src/jaegertracing/TraceID.cpp +++ b/src/jaegertracing/TraceID.cpp @@ -22,7 +22,7 @@ namespace jaegertracing { -TraceID TraceID::fromStream(std::istream& in) +TraceID TraceID::parseJaegerFormat(std::istream& in) { TraceID traceID; constexpr auto kMaxChars = static_cast(32); @@ -46,4 +46,40 @@ TraceID TraceID::fromStream(std::istream& in) return traceID; } +TraceID TraceID::parseW3CFormat(std::istream& in) +{ + TraceID traceID; + constexpr auto kMaxChars = static_cast(32); + auto buffer = utils::HexParsing::readSegment(in, kMaxChars, '-'); + + if (buffer.empty() || buffer.size() != kMaxChars) { + return TraceID(); + } + + auto beginLowStr = std::end(buffer) - kMaxChars / 2; + const std::string highStr(std::begin(buffer), beginLowStr); + traceID._high = utils::HexParsing::decodeHex(highStr); + const std::string lowStr(beginLowStr, std::end(buffer)); + traceID._low = utils::HexParsing::decodeHex(lowStr); + + return traceID; +} + +TraceID TraceID::fromStream(std::istream& in, PropagationFormat format) +{ + switch (format) { + case PropagationFormat::JAEGER: + return parseJaegerFormat(in); + case PropagationFormat::W3C: + return parseW3CFormat(in); + } + + return TraceID(); +} + +TraceID TraceID::fromStream(std::istream& in) +{ + return fromStream(in, PropagationFormat::JAEGER); +} + } // namespace jaegertracing diff --git a/src/jaegertracing/TraceID.h b/src/jaegertracing/TraceID.h index 867f0c29..e25f7bbf 100644 --- a/src/jaegertracing/TraceID.h +++ b/src/jaegertracing/TraceID.h @@ -21,10 +21,15 @@ #include #include +#include "jaegertracing/propagation/Format.h" + namespace jaegertracing { class TraceID { public: + using PropagationFormat = propagation::Format; + + static TraceID fromStream(std::istream& in, PropagationFormat format); static TraceID fromStream(std::istream& in); TraceID() @@ -41,17 +46,31 @@ class TraceID { bool isValid() const { return _high != 0 || _low != 0; } template - void print(Stream& out) const + void print(Stream& out, PropagationFormat format) const { - if (_high == 0) { - out << std::hex << _low; - } - else { - out << std::hex << _high << std::setw(16) << std::setfill('0') - << std::hex << _low; + switch (format) { + case PropagationFormat::JAEGER: + if (_high == 0) { + out << std::hex << _low; + } + else { + out << std::hex << _high << std::setw(16) << std::setfill('0') + << std::hex << _low; + } + break; + case PropagationFormat::W3C: + out << std::setw(16) << std::setfill('0') << std::hex << _high; + out << std::setw(16) << std::setfill('0') << std::hex << _low; + break; } } + template + void print(Stream& out) const + { + print(out, PropagationFormat::JAEGER); + } + uint64_t high() const { return _high; } uint64_t low() const { return _low; } @@ -62,6 +81,9 @@ class TraceID { } private: + static TraceID parseJaegerFormat(std::istream& in); + static TraceID parseW3CFormat(std::istream& in); + uint64_t _high; uint64_t _low; }; diff --git a/src/jaegertracing/TraceIDTest.cpp b/src/jaegertracing/TraceIDTest.cpp index ece21cfe..db690e72 100644 --- a/src/jaegertracing/TraceIDTest.cpp +++ b/src/jaegertracing/TraceIDTest.cpp @@ -20,11 +20,36 @@ namespace jaegertracing { -TEST(TraceID, testPrint) +using PropagationFormat = propagation::Format; + +TEST(TraceID, testPrintJaegerFormat) { std::ostringstream oss; - oss << TraceID(0, 10); + TraceID(0, 10).print(oss, PropagationFormat::JAEGER); ASSERT_EQ("a", oss.str()); } +TEST(TraceID, testPrintW3CFormat) +{ + std::ostringstream oss; + TraceID(0, 10).print(oss, PropagationFormat::W3C); + ASSERT_EQ("0000000000000000000000000000000a", oss.str()); +} + +TEST(TraceID, testfromStreamJaegerFormat) +{ + std::stringstream ss; + ss << "a"; + auto traceID = TraceID::fromStream(ss, PropagationFormat::JAEGER); + ASSERT_EQ(TraceID(0, 10), traceID); +} + +TEST(TraceID, testfromStreamW3CFormat) +{ + std::stringstream ss; + ss << "0000000000000000000000000000000a"; + auto traceID = TraceID::fromStream(ss, PropagationFormat::JAEGER); + ASSERT_EQ(TraceID(0, 10), traceID); +} + } // namespace jaegertracing diff --git a/src/jaegertracing/TracerTest.cpp b/src/jaegertracing/TracerTest.cpp index 3d5d8889..d780b8a7 100644 --- a/src/jaegertracing/TracerTest.cpp +++ b/src/jaegertracing/TracerTest.cpp @@ -463,6 +463,46 @@ TEST(Tracer, testPropagation) tracer->Close(); } +TEST(Tracer, testPropagationWithW3CHeaderAndFormat) +{ + const auto handle = + testutils::TracerUtil::installGlobalTracer(propagation::Format::W3C); + const auto tracer = + std::static_pointer_cast(opentracing::Tracer::Global()); + const std::unique_ptr span(static_cast( + tracer->StartSpanWithOptions("test-inject", {}).release())); + const auto spanContext = span->context(); + + std::ostringstream oss; + oss << "00"; + oss << '-'; + oss << std::setw(16) << std::setfill('0') << std::hex + << spanContext.traceID().high() << std::hex + << spanContext.traceID().low(); + oss << '-'; + oss << std::setw(16) << std::setfill('0') << std::hex + << spanContext.spanID(); + oss << '-'; + oss << (spanContext.isSampled() ? "01" : "00"); + + StrMap headerMap; + WriterMock headerWriter(headerMap); + ASSERT_TRUE( + static_cast(tracer->Inject(span->context(), headerWriter))); + ASSERT_EQ(1, headerMap.size()); + ASSERT_EQ(oss.str(), headerMap.at(kW3CTraceContextHeaderName)); + + ReaderMock headerReader(headerMap); + auto result = tracer->Extract(headerReader); + ASSERT_TRUE(static_cast(result)); + std::unique_ptr extractedCtx( + static_cast(result->release())); + ASSERT_TRUE(static_cast(extractedCtx)); + ASSERT_EQ(span->context(), *extractedCtx); + + tracer->Close(); +} + TEST(Tracer, testTracerTags) { std::vector tags; diff --git a/src/jaegertracing/propagation/Format.cpp b/src/jaegertracing/propagation/Format.cpp new file mode 100644 index 00000000..7d5c4d81 --- /dev/null +++ b/src/jaegertracing/propagation/Format.cpp @@ -0,0 +1,18 @@ + +/* + * Copyright (c) 2020 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jaegertracing/propagation/Format.h" diff --git a/src/jaegertracing/propagation/Format.h b/src/jaegertracing/propagation/Format.h new file mode 100644 index 00000000..f0b55f6d --- /dev/null +++ b/src/jaegertracing/propagation/Format.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JAEGERTRACING_PROPAGATION_FORMAT_H +#define JAEGERTRACING_PROPAGATION_FORMAT_H + +namespace jaegertracing { +namespace propagation { + +enum Format { JAEGER, W3C }; + +} // namespace propagation +} // namespace jaegertracing + +#endif // JAEGERTRACING_PROPAGATION_FORMAT_H \ No newline at end of file diff --git a/src/jaegertracing/propagation/HeadersConfig.h b/src/jaegertracing/propagation/HeadersConfig.h index 4ae21355..61ae9c0c 100644 --- a/src/jaegertracing/propagation/HeadersConfig.h +++ b/src/jaegertracing/propagation/HeadersConfig.h @@ -18,6 +18,7 @@ #define JAEGERTRACING_PROPAGATION_HEADERSCONFIG_H #include "jaegertracing/Constants.h" +#include "jaegertracing/propagation/Format.h" #include "jaegertracing/utils/YAML.h" #include @@ -45,11 +46,16 @@ class HeadersConfig { const auto traceBaggageHeaderPrefix = utils::yaml::findOrDefault( configYAML, "traceBaggageHeaderPrefix", ""); - - return HeadersConfig(jaegerDebugHeader, - jaegerBaggageHeader, - traceContextHeaderName, - traceBaggageHeaderPrefix); + const auto traceContextHeaderFormat = + utils::yaml::findOrDefault( + configYAML, "TraceContextHeaderFormat", ""); + + return HeadersConfig( + jaegerDebugHeader, + jaegerBaggageHeader, + traceContextHeaderName, + traceBaggageHeaderPrefix, + traceContextHeaderFormat == "W3C" ? Format::W3C : Format::JAEGER); } #endif // JAEGERTRACING_WITH_YAML_CPP @@ -74,6 +80,29 @@ class HeadersConfig { , _traceBaggageHeaderPrefix(traceBaggageHeaderPrefix.empty() ? kTraceBaggageHeaderPrefix : traceBaggageHeaderPrefix) + , _traceContextHeaderFormat(Format::JAEGER) + { + } + + HeadersConfig(const std::string& jaegerDebugHeader, + const std::string& jaegerBaggageHeader, + const std::string& traceContextHeaderName, + const std::string& traceBaggageHeaderPrefix, + Format traceContextHeaderFormat) + : _jaegerDebugHeader(jaegerDebugHeader.empty() ? kJaegerDebugHeader + : jaegerDebugHeader) + , _jaegerBaggageHeader(jaegerBaggageHeader.empty() + ? kJaegerBaggageHeader + : jaegerBaggageHeader) + , _traceContextHeaderName(traceContextHeaderName.empty() + ? (traceContextHeaderFormat == Format::W3C + ? kW3CTraceContextHeaderName + : kTraceContextHeaderName) + : traceContextHeaderName) + , _traceBaggageHeaderPrefix(traceBaggageHeaderPrefix.empty() + ? kTraceBaggageHeaderPrefix + : traceBaggageHeaderPrefix) + , _traceContextHeaderFormat(traceContextHeaderFormat) { } @@ -94,11 +123,17 @@ class HeadersConfig { return _traceContextHeaderName; } + Format traceContextHeaderFormat() const + { + return _traceContextHeaderFormat; + } + private: std::string _jaegerDebugHeader; std::string _jaegerBaggageHeader; std::string _traceContextHeaderName; std::string _traceBaggageHeaderPrefix; + Format _traceContextHeaderFormat; }; } // namespace propagation diff --git a/src/jaegertracing/propagation/Propagator.h b/src/jaegertracing/propagation/Propagator.h index bf04be81..6bdf9b51 100644 --- a/src/jaegertracing/propagation/Propagator.h +++ b/src/jaegertracing/propagation/Propagator.h @@ -69,7 +69,9 @@ class Propagator : public Extractor, public Injector { if (key == _headerKeys.traceContextHeaderName()) { const auto safeValue = decodeValue(value); std::istringstream iss(safeValue); - if (!(iss >> ctx) || ctx == SpanContext()) { + ctx = SpanContext::fromStream( + iss, _headerKeys.traceContextHeaderFormat()); + if (!iss || ctx == SpanContext()) { return opentracing::make_expected_from_error( opentracing::span_context_corrupted_error); } @@ -120,7 +122,7 @@ class Propagator : public Extractor, public Injector { void inject(const SpanContext& ctx, const Writer& writer) const override { std::ostringstream oss; - oss << ctx; + ctx.print(oss, _headerKeys.traceContextHeaderFormat()); writer.Set(_headerKeys.traceContextHeaderName(), oss.str()); ctx.forEachBaggageItem( [this, &writer](const std::string& key, const std::string& value) { diff --git a/src/jaegertracing/testutils/TracerUtil.cpp b/src/jaegertracing/testutils/TracerUtil.cpp index ffa65c1f..821044b8 100644 --- a/src/jaegertracing/testutils/TracerUtil.cpp +++ b/src/jaegertracing/testutils/TracerUtil.cpp @@ -1,82 +1,87 @@ -/* - * Copyright (c) 2017 Uber Technologies, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "jaegertracing/testutils/TracerUtil.h" -#include "jaegertracing/Config.h" -#include "jaegertracing/Logging.h" -#include "jaegertracing/Tracer.h" -#include "jaegertracing/baggage/RestrictionsConfig.h" -#include "jaegertracing/net/IPAddress.h" -#include "jaegertracing/propagation/HeadersConfig.h" -#include "jaegertracing/reporters/Config.h" -#include "jaegertracing/samplers/Config.h" -#include -#include -#include - -namespace jaegertracing { -namespace testutils { -namespace TracerUtil { - -std::shared_ptr installGlobalTracer() -{ - std::unique_ptr handle(new ResourceHandle()); - handle->_mockAgent->start(); - std::ostringstream samplingServerURLStream; - samplingServerURLStream - << "http://" << handle->_mockAgent->samplingServerAddress().authority(); - Config config( - false, - samplers::Config("const", - 1, - samplingServerURLStream.str(), - 0, - samplers::Config::Clock::duration()), - reporters::Config(0, - reporters::Config::Clock::duration(), - false, - handle->_mockAgent->spanServerAddress().authority()), - propagation::HeadersConfig(), - baggage::RestrictionsConfig()); - - auto tracer = Tracer::make("test-service", config, logging::nullLogger()); - opentracing::Tracer::InitGlobal(tracer); - return std::move(handle); -} - -std::shared_ptr buildTracer(const std::string& endpoint) -{ - std::ostringstream samplingServerURLStream; - Config config( - false, - samplers::Config("const", - 1, - samplingServerURLStream.str(), - 0, - samplers::Config::Clock::duration()), - reporters::Config(0, - std::chrono::milliseconds(100), - false, "", endpoint), - propagation::HeadersConfig(), - baggage::RestrictionsConfig()); - - auto tracer = Tracer::make("test-service", config, logging::nullLogger()); - return tracer; -} - -} // namespace TracerUtil -} // namespace testutils -} // namespace jaegertracing +/* + * Copyright (c) 2017 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jaegertracing/testutils/TracerUtil.h" +#include "jaegertracing/Config.h" +#include "jaegertracing/Logging.h" +#include "jaegertracing/Tracer.h" +#include "jaegertracing/baggage/RestrictionsConfig.h" +#include "jaegertracing/net/IPAddress.h" +#include "jaegertracing/propagation/HeadersConfig.h" +#include "jaegertracing/reporters/Config.h" +#include "jaegertracing/samplers/Config.h" +#include +#include +#include + +namespace jaegertracing { +namespace testutils { +namespace TracerUtil { + +std::shared_ptr installGlobalTracer(PropagationFormat format) +{ + std::unique_ptr handle(new ResourceHandle()); + handle->_mockAgent->start(); + std::ostringstream samplingServerURLStream; + samplingServerURLStream + << "http://" << handle->_mockAgent->samplingServerAddress().authority(); + Config config( + false, + samplers::Config("const", + 1, + samplingServerURLStream.str(), + 0, + samplers::Config::Clock::duration()), + reporters::Config(0, + reporters::Config::Clock::duration(), + false, + handle->_mockAgent->spanServerAddress().authority()), + propagation::HeadersConfig("", "", "", "", format), + baggage::RestrictionsConfig()); + + auto tracer = Tracer::make("test-service", config, logging::nullLogger()); + opentracing::Tracer::InitGlobal(tracer); + return std::move(handle); +} + +std::shared_ptr installGlobalTracer() +{ + return installGlobalTracer(PropagationFormat::JAEGER); +} + +std::shared_ptr buildTracer(const std::string& endpoint) +{ + std::ostringstream samplingServerURLStream; + Config config( + false, + samplers::Config("const", + 1, + samplingServerURLStream.str(), + 0, + samplers::Config::Clock::duration()), + reporters::Config(0, + std::chrono::milliseconds(100), + false, "", endpoint), + propagation::HeadersConfig(), + baggage::RestrictionsConfig()); + + auto tracer = Tracer::make("test-service", config, logging::nullLogger()); + return tracer; +} + +} // namespace TracerUtil +} // namespace testutils +} // namespace jaegertracing diff --git a/src/jaegertracing/testutils/TracerUtil.h b/src/jaegertracing/testutils/TracerUtil.h index a61e5700..3aa635e2 100644 --- a/src/jaegertracing/testutils/TracerUtil.h +++ b/src/jaegertracing/testutils/TracerUtil.h @@ -20,12 +20,15 @@ #include #include "jaegertracing/Tracer.h" +#include "jaegertracing/propagation/Format.h" #include "jaegertracing/testutils/MockAgent.h" namespace jaegertracing { namespace testutils { namespace TracerUtil { +using PropagationFormat = propagation::Format; + struct ResourceHandle { ResourceHandle() : _mockAgent(testutils::MockAgent::make()) @@ -40,6 +43,7 @@ struct ResourceHandle { std::shared_ptr _mockAgent; }; +std::shared_ptr installGlobalTracer(PropagationFormat format); std::shared_ptr installGlobalTracer(); std::shared_ptr buildTracer(const std::string& endpoint); From bca7ba6b76843fb996a8da6c0d9851610b2d2532 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Mon, 30 Nov 2020 19:28:37 +0100 Subject: [PATCH 02/10] W3C should be lowercase as mentioned in https://www.jaegertracing.io/docs/1.21/client-features/, Signed-off-by: Tobias Stadler --- src/jaegertracing/ConfigTest.cpp | 2 +- src/jaegertracing/propagation/HeadersConfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jaegertracing/ConfigTest.cpp b/src/jaegertracing/ConfigTest.cpp index 6679735e..278e706e 100644 --- a/src/jaegertracing/ConfigTest.cpp +++ b/src/jaegertracing/ConfigTest.cpp @@ -99,7 +99,7 @@ TEST(Config, testW3CTraceContextHeaderFormat) { constexpr auto kConfigYAML = R"cfg( headers: - TraceContextHeaderFormat: W3C + TraceContextHeaderFormat: w3c )cfg"; const auto config = Config::parse(YAML::Load(kConfigYAML)); ASSERT_EQ(kW3CTraceContextHeaderName, diff --git a/src/jaegertracing/propagation/HeadersConfig.h b/src/jaegertracing/propagation/HeadersConfig.h index 61ae9c0c..0a5169c8 100644 --- a/src/jaegertracing/propagation/HeadersConfig.h +++ b/src/jaegertracing/propagation/HeadersConfig.h @@ -55,7 +55,7 @@ class HeadersConfig { jaegerBaggageHeader, traceContextHeaderName, traceBaggageHeaderPrefix, - traceContextHeaderFormat == "W3C" ? Format::W3C : Format::JAEGER); + traceContextHeaderFormat == "w3c" ? Format::W3C : Format::JAEGER); } #endif // JAEGERTRACING_WITH_YAML_CPP From 0d5f0e71ae6d8317d957be950980cd9377371480 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Mon, 30 Nov 2020 20:01:37 +0100 Subject: [PATCH 03/10] Added support for setting the propagation format via environment variables Signed-off-by: Tobias Stadler --- README.md | 1 + src/jaegertracing/Config.cpp | 1 + src/jaegertracing/ConfigTest.cpp | 7 +++++++ src/jaegertracing/propagation/HeadersConfig.h | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/README.md b/README.md index 36881bb9..6cfb5635 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ JAEGER_DISABLED _(not recommended)_ | Instructs the Configuration to return a no JAEGER_AGENT_HOST | The hostname for communicating with agent via UDP JAEGER_AGENT_PORT | The port for communicating with agent via UDP JAEGER_ENDPOINT | The traces endpoint, in case the client should connect directly to the Collector, like http://jaeger-collector:14268/api/traces +JAEGER_PROPAGATION | The propagation format used by the tracer. Supported values are jaeger and w3c JAEGER_REPORTER_LOG_SPANS | Whether the reporter should also log the spans JAEGER_REPORTER_MAX_QUEUE_SIZE | The reporter's maximum queue size JAEGER_REPORTER_FLUSH_INTERVAL | The reporter's flush interval (ms) diff --git a/src/jaegertracing/Config.cpp b/src/jaegertracing/Config.cpp index abf28bcc..f3020df0 100644 --- a/src/jaegertracing/Config.cpp +++ b/src/jaegertracing/Config.cpp @@ -62,6 +62,7 @@ void Config::fromEnv() } _reporter.fromEnv(); _sampler.fromEnv(); + _headers.fromEnv(); } } // namespace jaegertracing diff --git a/src/jaegertracing/ConfigTest.cpp b/src/jaegertracing/ConfigTest.cpp index 278e706e..b342679b 100644 --- a/src/jaegertracing/ConfigTest.cpp +++ b/src/jaegertracing/ConfigTest.cpp @@ -194,6 +194,12 @@ TEST(Config, testFromEnv) ASSERT_EQ(std::string("host33:445"), config.reporter().localAgentHostPort()); + testutils::EnvVariable::setEnv("JAEGER_PROPAGATION", "w3c"); + + config.fromEnv(); + ASSERT_EQ(kW3CTraceContextHeaderName, config.headers().traceContextHeaderName()); + ASSERT_EQ(propagation::Format::W3C, config.headers().traceContextHeaderFormat()); + testutils::EnvVariable::setEnv("JAEGER_AGENT_HOST", ""); testutils::EnvVariable::setEnv("JAEGER_AGENT_PORT", ""); testutils::EnvVariable::setEnv("JAEGER_ENDPOINT", ""); @@ -205,6 +211,7 @@ TEST(Config, testFromEnv) testutils::EnvVariable::setEnv("JAEGER_SERVICE_NAME", ""); testutils::EnvVariable::setEnv("JAEGER_TAGS", ""); testutils::EnvVariable::setEnv("JAEGER_DISABLED", ""); + testutils::EnvVariable::setEnv("JAEGER_PROPAGATION", ""); } } // namespace jaegertracing diff --git a/src/jaegertracing/propagation/HeadersConfig.h b/src/jaegertracing/propagation/HeadersConfig.h index 0a5169c8..7139f2be 100644 --- a/src/jaegertracing/propagation/HeadersConfig.h +++ b/src/jaegertracing/propagation/HeadersConfig.h @@ -19,6 +19,7 @@ #include "jaegertracing/Constants.h" #include "jaegertracing/propagation/Format.h" +#include "jaegertracing/utils/EnvVariable.h" #include "jaegertracing/utils/YAML.h" #include @@ -27,6 +28,9 @@ namespace propagation { class HeadersConfig { public: + + static constexpr auto kJAEGER_PROPAGATION_ENV_PROP = "JAEGER_PROPAGATION"; + #ifdef JAEGERTRACING_WITH_YAML_CPP static HeadersConfig parse(const YAML::Node& configYAML) @@ -128,6 +132,20 @@ class HeadersConfig { return _traceContextHeaderFormat; } + void fromEnv() { + const auto propagationFormat = + utils::EnvVariable::getStringVariable(kJAEGER_PROPAGATION_ENV_PROP); + if (!propagationFormat.empty()) { + if(propagationFormat == "jaeger") { + _traceContextHeaderName = kTraceContextHeaderName; + _traceContextHeaderFormat: Format::JAEGER; + } else if(propagationFormat == "w3c") { + _traceContextHeaderName = kW3CTraceContextHeaderName; + _traceContextHeaderFormat = Format::W3C; + } + } + } + private: std::string _jaegerDebugHeader; std::string _jaegerBaggageHeader; From 918a852cb2097032f4b91991ddc27de896d1983b Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Wed, 2 Dec 2020 20:04:11 +0100 Subject: [PATCH 04/10] Fix assignment Signed-off-by: Tobias Stadler --- src/jaegertracing/propagation/HeadersConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jaegertracing/propagation/HeadersConfig.h b/src/jaegertracing/propagation/HeadersConfig.h index 7139f2be..771cb922 100644 --- a/src/jaegertracing/propagation/HeadersConfig.h +++ b/src/jaegertracing/propagation/HeadersConfig.h @@ -138,7 +138,7 @@ class HeadersConfig { if (!propagationFormat.empty()) { if(propagationFormat == "jaeger") { _traceContextHeaderName = kTraceContextHeaderName; - _traceContextHeaderFormat: Format::JAEGER; + _traceContextHeaderFormat = Format::JAEGER; } else if(propagationFormat == "w3c") { _traceContextHeaderName = kW3CTraceContextHeaderName; _traceContextHeaderFormat = Format::W3C; From d5ac7068883e84fe5df9930309c2d1fcb840fd80 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Wed, 2 Dec 2020 20:44:24 +0100 Subject: [PATCH 05/10] Implemented Support for W3C tracestate Signed-off-by: Tobias Stadler --- src/jaegertracing/ConfigTest.cpp | 8 +++-- src/jaegertracing/Constants.h.in | 3 +- src/jaegertracing/SpanContext.h | 21 +++++++++++--- src/jaegertracing/TracerTest.cpp | 26 +++++++++++++++++ src/jaegertracing/propagation/HeadersConfig.h | 29 +++++++++++++++---- src/jaegertracing/propagation/Propagator.h | 15 ++++++++-- src/jaegertracing/testutils/TracerUtil.cpp | 2 +- 7 files changed, 88 insertions(+), 16 deletions(-) diff --git a/src/jaegertracing/ConfigTest.cpp b/src/jaegertracing/ConfigTest.cpp index b342679b..a23915ca 100644 --- a/src/jaegertracing/ConfigTest.cpp +++ b/src/jaegertracing/ConfigTest.cpp @@ -197,8 +197,12 @@ TEST(Config, testFromEnv) testutils::EnvVariable::setEnv("JAEGER_PROPAGATION", "w3c"); config.fromEnv(); - ASSERT_EQ(kW3CTraceContextHeaderName, config.headers().traceContextHeaderName()); - ASSERT_EQ(propagation::Format::W3C, config.headers().traceContextHeaderFormat()); + ASSERT_EQ(kW3CTraceContextHeaderName, + config.headers().traceContextHeaderName()); + ASSERT_EQ(kW3CTraceStateHeaderName, + config.headers().traceStateHeaderName()); + ASSERT_EQ(propagation::Format::W3C, + config.headers().traceContextHeaderFormat()); testutils::EnvVariable::setEnv("JAEGER_AGENT_HOST", ""); testutils::EnvVariable::setEnv("JAEGER_AGENT_PORT", ""); diff --git a/src/jaegertracing/Constants.h.in b/src/jaegertracing/Constants.h.in index 2c316b70..97eb6dfc 100644 --- a/src/jaegertracing/Constants.h.in +++ b/src/jaegertracing/Constants.h.in @@ -31,8 +31,9 @@ static constexpr auto kSamplerTypeTagKey = "sampler.type"; static constexpr auto kSamplerParamTagKey = "sampler.param"; static constexpr auto kTraceContextHeaderName = "uber-trace-id"; static constexpr auto kTracerStateHeaderName = kTraceContextHeaderName; -static constexpr auto kW3CTraceContextHeaderName = "traceparent"; static constexpr auto kTraceBaggageHeaderPrefix = "uberctx-"; +static constexpr auto kW3CTraceContextHeaderName = "traceparent"; +static constexpr auto kW3CTraceStateHeaderName = "tracestate"; static constexpr auto kSamplerTypeConst = "const"; static constexpr auto kSamplerTypeRemote = "remote"; static constexpr auto kSamplerTypeProbabilistic = "probabilistic"; diff --git a/src/jaegertracing/SpanContext.h b/src/jaegertracing/SpanContext.h index dd4a5432..663c2cb1 100644 --- a/src/jaegertracing/SpanContext.h +++ b/src/jaegertracing/SpanContext.h @@ -56,13 +56,15 @@ class SpanContext : public opentracing::SpanContext { uint64_t parentID, unsigned char flags, const StrMap& baggage, - const std::string& debugID = "") + const std::string& debugID = "", + const std::string& traceState = "") : _traceID(traceID) , _spanID(spanID) , _parentID(parentID) , _flags(flags) , _baggage(baggage) , _debugID(debugID) + , _traceState(traceState) , _mutex() { } @@ -74,6 +76,7 @@ class SpanContext : public opentracing::SpanContext { , _flags(ctx._flags) , _baggage(ctx._baggage) , _debugID(ctx._debugID) + , _traceState(ctx._traceState) { } @@ -92,6 +95,7 @@ class SpanContext : public opentracing::SpanContext { swap(_flags, ctx._flags); swap(_baggage, ctx._baggage); swap(_debugID, ctx._debugID); + swap(_traceState, ctx._traceState); } friend void swap(SpanContext& lhs, SpanContext& rhs) { lhs.swap(rhs); } @@ -107,8 +111,13 @@ class SpanContext : public opentracing::SpanContext { SpanContext withBaggage(const StrMap& baggage) const { std::lock_guard lock(_mutex); - return SpanContext( - _traceID, _spanID, _parentID, _flags, baggage, _debugID); + return SpanContext(_traceID, + _spanID, + _parentID, + _flags, + baggage, + _debugID, + _traceState); } template @@ -137,6 +146,8 @@ class SpanContext : public opentracing::SpanContext { const std::string& debugID() const { return _debugID; } + const std::string& traceState() const { return _traceState; } + bool isSampled() const { return _flags & static_cast(Flag::kSampled); @@ -208,7 +219,8 @@ class SpanContext : public opentracing::SpanContext { } return lhs._traceID == rhs._traceID && lhs._spanID == rhs._spanID && lhs._parentID == rhs._parentID && lhs._flags == rhs._flags && - lhs._debugID == rhs._debugID; + lhs._debugID == rhs._debugID && + lhs._traceState == rhs._traceState; } friend bool operator!=(const SpanContext& lhs, const SpanContext& rhs) @@ -226,6 +238,7 @@ class SpanContext : public opentracing::SpanContext { unsigned char _flags; StrMap _baggage; std::string _debugID; + std::string _traceState; mutable std::mutex _mutex; // Protects _baggage. }; diff --git a/src/jaegertracing/TracerTest.cpp b/src/jaegertracing/TracerTest.cpp index d780b8a7..64a0e923 100644 --- a/src/jaegertracing/TracerTest.cpp +++ b/src/jaegertracing/TracerTest.cpp @@ -503,6 +503,32 @@ TEST(Tracer, testPropagationWithW3CHeaderAndFormat) tracer->Close(); } +TEST(Tracer, testPropagationWithW3CTraceState) +{ + const auto handle = + testutils::TracerUtil::installGlobalTracer(propagation::Format::W3C); + const auto tracer = + std::static_pointer_cast(opentracing::Tracer::Global()); + StrMap headerMap{ + { kW3CTraceContextHeaderName, + "00-00000000000000000000000000000001-0000000000000001-01" }, + { kW3CTraceStateHeaderName, "foo=bar" } + }; + + ReaderMock headerReader(headerMap); + auto result = tracer->Extract(headerReader); + std::unique_ptr ctx( + static_cast(result->release())); + ASSERT_EQ("foo=bar", ctx->traceState()); + + headerMap.clear(); + + WriterMock headerWriter(headerMap); + tracer->Inject(*ctx, headerWriter); + ASSERT_EQ(2, headerMap.size()); + ASSERT_EQ("foo=bar", headerMap.at(kW3CTraceStateHeaderName)); +} + TEST(Tracer, testTracerTags) { std::vector tags; diff --git a/src/jaegertracing/propagation/HeadersConfig.h b/src/jaegertracing/propagation/HeadersConfig.h index 771cb922..3d7a9fc5 100644 --- a/src/jaegertracing/propagation/HeadersConfig.h +++ b/src/jaegertracing/propagation/HeadersConfig.h @@ -50,6 +50,9 @@ class HeadersConfig { const auto traceBaggageHeaderPrefix = utils::yaml::findOrDefault( configYAML, "traceBaggageHeaderPrefix", ""); + const auto traceStateHeaderName = + utils::yaml::findOrDefault( + configYAML, "TraceStateHeaderName", ""); const auto traceContextHeaderFormat = utils::yaml::findOrDefault( configYAML, "TraceContextHeaderFormat", ""); @@ -59,13 +62,14 @@ class HeadersConfig { jaegerBaggageHeader, traceContextHeaderName, traceBaggageHeaderPrefix, + traceStateHeaderName, traceContextHeaderFormat == "w3c" ? Format::W3C : Format::JAEGER); } #endif // JAEGERTRACING_WITH_YAML_CPP HeadersConfig() - : HeadersConfig("", "", "", "") + : HeadersConfig("", "", "", "", "", Format::JAEGER) { } @@ -92,6 +96,7 @@ class HeadersConfig { const std::string& jaegerBaggageHeader, const std::string& traceContextHeaderName, const std::string& traceBaggageHeaderPrefix, + const std::string& traceStateHeaderName, Format traceContextHeaderFormat) : _jaegerDebugHeader(jaegerDebugHeader.empty() ? kJaegerDebugHeader : jaegerDebugHeader) @@ -106,6 +111,11 @@ class HeadersConfig { , _traceBaggageHeaderPrefix(traceBaggageHeaderPrefix.empty() ? kTraceBaggageHeaderPrefix : traceBaggageHeaderPrefix) + , _traceStateHeaderName(traceStateHeaderName.empty() + ? (traceContextHeaderFormat == Format::W3C + ? kW3CTraceStateHeaderName + : "") + : traceStateHeaderName) , _traceContextHeaderFormat(traceContextHeaderFormat) { } @@ -127,20 +137,28 @@ class HeadersConfig { return _traceContextHeaderName; } + const std::string& traceStateHeaderName() const + { + return _traceStateHeaderName; + } + Format traceContextHeaderFormat() const { return _traceContextHeaderFormat; } - void fromEnv() { + void fromEnv() + { const auto propagationFormat = - utils::EnvVariable::getStringVariable(kJAEGER_PROPAGATION_ENV_PROP); + utils::EnvVariable::getStringVariable(kJAEGER_PROPAGATION_ENV_PROP); if (!propagationFormat.empty()) { - if(propagationFormat == "jaeger") { + if (propagationFormat == "jaeger") { _traceContextHeaderName = kTraceContextHeaderName; _traceContextHeaderFormat = Format::JAEGER; - } else if(propagationFormat == "w3c") { + } + else if (propagationFormat == "w3c") { _traceContextHeaderName = kW3CTraceContextHeaderName; + _traceStateHeaderName = kW3CTraceStateHeaderName; _traceContextHeaderFormat = Format::W3C; } } @@ -151,6 +169,7 @@ class HeadersConfig { std::string _jaegerBaggageHeader; std::string _traceContextHeaderName; std::string _traceBaggageHeaderPrefix; + std::string _traceStateHeaderName; Format _traceContextHeaderFormat; }; diff --git a/src/jaegertracing/propagation/Propagator.h b/src/jaegertracing/propagation/Propagator.h index 6bdf9b51..840e69d3 100644 --- a/src/jaegertracing/propagation/Propagator.h +++ b/src/jaegertracing/propagation/Propagator.h @@ -62,9 +62,10 @@ class Propagator : public Extractor, public Injector { SpanContext ctx; StrMap baggage; std::string debugID; + std::string traceState; const auto result = reader.ForeachKey( - [this, &ctx, &debugID, &baggage](const std::string& rawKey, - const std::string& value) { + [this, &ctx, &debugID, &baggage, &traceState]( + const std::string& rawKey, const std::string& value) { const auto key = normalizeKey(rawKey); if (key == _headerKeys.traceContextHeaderName()) { const auto safeValue = decodeValue(value); @@ -84,6 +85,9 @@ class Propagator : public Extractor, public Injector { baggage[pair.first] = pair.second; } } + else if (key == _headerKeys.traceStateHeaderName()) { + traceState = value; + } else { const auto prefix = _headerKeys.traceBaggageHeaderPrefix(); if (key.size() >= prefix.size() && @@ -116,7 +120,8 @@ class Propagator : public Extractor, public Injector { ctx.parentID(), flags, baggage, - debugID); + debugID, + traceState); } void inject(const SpanContext& ctx, const Writer& writer) const override @@ -131,6 +136,10 @@ class Propagator : public Extractor, public Injector { writer.Set(safeKey, safeValue); return true; }); + if (!_headerKeys.traceStateHeaderName().empty() && + !ctx.traceState().empty()) { + writer.Set(_headerKeys.traceStateHeaderName(), ctx.traceState()); + } } protected: diff --git a/src/jaegertracing/testutils/TracerUtil.cpp b/src/jaegertracing/testutils/TracerUtil.cpp index 821044b8..370dfc41 100644 --- a/src/jaegertracing/testutils/TracerUtil.cpp +++ b/src/jaegertracing/testutils/TracerUtil.cpp @@ -49,7 +49,7 @@ std::shared_ptr installGlobalTracer(PropagationFormat format) reporters::Config::Clock::duration(), false, handle->_mockAgent->spanServerAddress().authority()), - propagation::HeadersConfig("", "", "", "", format), + propagation::HeadersConfig("", "", "", "", "", format), baggage::RestrictionsConfig()); auto tracer = Tracer::make("test-service", config, logging::nullLogger()); From 1f3ed2a4c653c5ecacd221ec8ec60887c74a94bd Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Sun, 6 Dec 2020 13:15:21 +0100 Subject: [PATCH 06/10] Extracted Jager porpagation and W3C propgation in their own classes Signed-off-by: Tobias Stadler --- CMakeLists.txt | 3 + src/jaegertracing/Config.cpp | 12 +- src/jaegertracing/Config.h | 23 +- src/jaegertracing/ConfigTest.cpp | 17 +- src/jaegertracing/Constants.h.in | 2 +- src/jaegertracing/SpanContext.cpp | 66 +----- src/jaegertracing/SpanContext.h | 37 +--- src/jaegertracing/SpanContextTest.cpp | 69 +----- src/jaegertracing/TraceID.cpp | 38 +--- src/jaegertracing/TraceID.h | 36 +-- src/jaegertracing/TraceIDTest.cpp | 29 +-- src/jaegertracing/Tracer.cpp | 21 +- src/jaegertracing/Tracer.h | 26 ++- src/jaegertracing/TracerTest.cpp | 7 +- src/jaegertracing/propagation/HeadersConfig.h | 84 +------ .../propagation/JaegerPropagator.cpp | 17 ++ .../propagation/JaegerPropagator.h | 158 ++++++++++++++ src/jaegertracing/propagation/Propagator.h | 132 ++--------- .../propagation/W3CPropagator.cpp | 17 ++ src/jaegertracing/propagation/W3CPropagator.h | 206 ++++++++++++++++++ .../propagation/W3CPropagatorTest.cpp | 165 ++++++++++++++ src/jaegertracing/testutils/TracerUtil.cpp | 22 +- src/jaegertracing/testutils/TracerUtil.h | 4 +- 23 files changed, 701 insertions(+), 490 deletions(-) create mode 100644 src/jaegertracing/propagation/JaegerPropagator.cpp create mode 100644 src/jaegertracing/propagation/JaegerPropagator.h create mode 100644 src/jaegertracing/propagation/W3CPropagator.cpp create mode 100644 src/jaegertracing/propagation/W3CPropagator.h create mode 100644 src/jaegertracing/propagation/W3CPropagatorTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cc07cff..59126138 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,6 +171,8 @@ set(SRC src/jaegertracing/propagation/HeadersConfig.cpp src/jaegertracing/propagation/Injector.cpp src/jaegertracing/propagation/Propagator.cpp + src/jaegertracing/propagation/JaegerPropagator.cpp + src/jaegertracing/propagation/W3CPropagator.cpp src/jaegertracing/reporters/CompositeReporter.cpp src/jaegertracing/reporters/Config.cpp src/jaegertracing/reporters/InMemoryReporter.cpp @@ -332,6 +334,7 @@ if(BUILD_TESTING) src/jaegertracing/net/http/MethodTest.cpp src/jaegertracing/net/http/ResponseTest.cpp src/jaegertracing/propagation/PropagatorTest.cpp + src/jaegertracing/propagation/W3CPropagatorTest.cpp src/jaegertracing/reporters/ConfigTest.cpp src/jaegertracing/reporters/ReporterTest.cpp src/jaegertracing/samplers/SamplerTest.cpp diff --git a/src/jaegertracing/Config.cpp b/src/jaegertracing/Config.cpp index f3020df0..57a5f437 100644 --- a/src/jaegertracing/Config.cpp +++ b/src/jaegertracing/Config.cpp @@ -32,6 +32,17 @@ void Config::fromEnv() _disabled = disabled.second; } + const auto propagationFormat = + utils::EnvVariable::getStringVariable(kJAEGER_PROPAGATION_ENV_PROP); + if(!propagationFormat.empty()) { + if (propagationFormat == "w3c") { + _propagationFormat = propagation::Format::W3C; + } + else { + _propagationFormat = propagation::Format::JAEGER; + } + } + const auto serviceName = utils::EnvVariable::getStringVariable(kJAEGER_SERVICE_NAME_ENV_PROP); if (!serviceName.empty()) { @@ -62,7 +73,6 @@ void Config::fromEnv() } _reporter.fromEnv(); _sampler.fromEnv(); - _headers.fromEnv(); } } // namespace jaegertracing diff --git a/src/jaegertracing/Config.h b/src/jaegertracing/Config.h index 2c9f0a32..6e7a67ca 100644 --- a/src/jaegertracing/Config.h +++ b/src/jaegertracing/Config.h @@ -22,6 +22,7 @@ #include "jaegertracing/Tag.h" #include "jaegertracing/baggage/RestrictionsConfig.h" #include "jaegertracing/propagation/HeadersConfig.h" +#include "jaegertracing/propagation/Format.h" #include "jaegertracing/reporters/Config.h" #include "jaegertracing/samplers/Config.h" #include "jaegertracing/utils/YAML.h" @@ -34,6 +35,7 @@ class Config { static constexpr auto kJAEGER_SERVICE_NAME_ENV_PROP = "JAEGER_SERVICE_NAME"; static constexpr auto kJAEGER_TAGS_ENV_PROP = "JAEGER_TAGS"; static constexpr auto kJAEGER_JAEGER_DISABLED_ENV_PROP = "JAEGER_DISABLED"; + static constexpr auto kJAEGER_PROPAGATION_ENV_PROP = "JAEGER_PROPAGATION"; #ifdef JAEGERTRACING_WITH_YAML_CPP @@ -48,6 +50,8 @@ class Config { const auto disabled = utils::yaml::findOrDefault(configYAML, "disabled", false); + const auto propagationFormat = utils::yaml::findOrDefault( + configYAML, "propagation_format", "jaeger"); const auto samplerNode = configYAML["sampler"]; const auto sampler = samplers::Config::parse(samplerNode); const auto reporterNode = configYAML["reporter"]; @@ -57,8 +61,15 @@ class Config { const auto baggageRestrictionsNode = configYAML["baggage_restrictions"]; const auto baggageRestrictions = baggage::RestrictionsConfig::parse(baggageRestrictionsNode); - return Config( - disabled, sampler, reporter, headers, baggageRestrictions, serviceName); + return Config(disabled, + sampler, + reporter, + headers, + baggageRestrictions, + serviceName, + std::vector(), + propagationFormat == "w3c" ? propagation::Format::W3C + : propagation::Format::JAEGER); } #endif // JAEGERTRACING_WITH_YAML_CPP @@ -71,8 +82,11 @@ class Config { const baggage::RestrictionsConfig& baggageRestrictions = baggage::RestrictionsConfig(), const std::string& serviceName = "", - const std::vector& tags = std::vector()) + const std::vector& tags = std::vector(), + const propagation::Format propagationFormat = + propagation::Format::JAEGER) : _disabled(disabled) + , _propagationFormat(propagationFormat) , _serviceName(serviceName) , _tags(tags) , _sampler(sampler) @@ -84,6 +98,8 @@ class Config { bool disabled() const { return _disabled; } + propagation::Format propagationFormat() const { return _propagationFormat; } + const samplers::Config& sampler() const { return _sampler; } const reporters::Config& reporter() const { return _reporter; } @@ -103,6 +119,7 @@ class Config { private: bool _disabled; + propagation::Format _propagationFormat; std::string _serviceName; std::vector< Tag > _tags; samplers::Config _sampler; diff --git a/src/jaegertracing/ConfigTest.cpp b/src/jaegertracing/ConfigTest.cpp index a23915ca..ccd2ec69 100644 --- a/src/jaegertracing/ConfigTest.cpp +++ b/src/jaegertracing/ConfigTest.cpp @@ -94,18 +94,14 @@ TEST(Config, testZeroSamplingParam) } } -TEST(Config, testW3CTraceContextHeaderFormat) +TEST(Config, testPropagationFormat) { { constexpr auto kConfigYAML = R"cfg( -headers: - TraceContextHeaderFormat: w3c +propagation_format: w3c )cfg"; const auto config = Config::parse(YAML::Load(kConfigYAML)); - ASSERT_EQ(kW3CTraceContextHeaderName, - config.headers().traceContextHeaderName()); - ASSERT_EQ(propagation::Format::W3C, - config.headers().traceContextHeaderFormat()); + ASSERT_EQ(propagation::Format::W3C, config.propagationFormat()); } } @@ -197,12 +193,7 @@ TEST(Config, testFromEnv) testutils::EnvVariable::setEnv("JAEGER_PROPAGATION", "w3c"); config.fromEnv(); - ASSERT_EQ(kW3CTraceContextHeaderName, - config.headers().traceContextHeaderName()); - ASSERT_EQ(kW3CTraceStateHeaderName, - config.headers().traceStateHeaderName()); - ASSERT_EQ(propagation::Format::W3C, - config.headers().traceContextHeaderFormat()); + ASSERT_EQ(propagation::Format::W3C, config.propagationFormat()); testutils::EnvVariable::setEnv("JAEGER_AGENT_HOST", ""); testutils::EnvVariable::setEnv("JAEGER_AGENT_PORT", ""); diff --git a/src/jaegertracing/Constants.h.in b/src/jaegertracing/Constants.h.in index 97eb6dfc..a235cf59 100644 --- a/src/jaegertracing/Constants.h.in +++ b/src/jaegertracing/Constants.h.in @@ -32,7 +32,7 @@ static constexpr auto kSamplerParamTagKey = "sampler.param"; static constexpr auto kTraceContextHeaderName = "uber-trace-id"; static constexpr auto kTracerStateHeaderName = kTraceContextHeaderName; static constexpr auto kTraceBaggageHeaderPrefix = "uberctx-"; -static constexpr auto kW3CTraceContextHeaderName = "traceparent"; +static constexpr auto kW3CTraceParentHeaderName = "traceparent"; static constexpr auto kW3CTraceStateHeaderName = "tracestate"; static constexpr auto kSamplerTypeConst = "const"; static constexpr auto kSamplerTypeRemote = "remote"; diff --git a/src/jaegertracing/SpanContext.cpp b/src/jaegertracing/SpanContext.cpp index 67f74f00..effbf11a 100644 --- a/src/jaegertracing/SpanContext.cpp +++ b/src/jaegertracing/SpanContext.cpp @@ -20,7 +20,7 @@ namespace jaegertracing { -SpanContext SpanContext::parseJaegerFormat(std::istream& in) +SpanContext SpanContext::fromStream(std::istream& in) { SpanContext spanContext; spanContext._traceID = TraceID::fromStream(in); @@ -65,68 +65,4 @@ SpanContext SpanContext::parseJaegerFormat(std::istream& in) return spanContext; } -SpanContext SpanContext::parseW3CFormat(std::istream& in) -{ - char ch = '\0'; - if (!in.get(ch) || ch != '0') { - return SpanContext(); - } - - if (!in.get(ch) || ch != '0') { - return SpanContext(); - } - - if (!in.get(ch) || ch != '-') { - return SpanContext(); - } - - SpanContext spanContext; - spanContext._traceID = TraceID::fromStream(in, PropagationFormat::W3C); - if (!spanContext._traceID.isValid()) { - return SpanContext(); - } - - if (!in.get(ch) || ch != '-') { - return SpanContext(); - } - - constexpr auto kMaxUInt64Chars = static_cast(16); - auto buffer = utils::HexParsing::readSegment(in, kMaxUInt64Chars, '-'); - if (buffer.empty()) { - return SpanContext(); - } - spanContext._spanID = utils::HexParsing::decodeHex(buffer); - - if (!in.get(ch) || ch != '-') { - return SpanContext(); - } - - constexpr auto kMaxByteChars = static_cast(2); - buffer = utils::HexParsing::readSegment(in, kMaxByteChars, '-'); - if (buffer.empty() || buffer.size() != 2) { - return SpanContext(); - } - spanContext._flags = utils::HexParsing::decodeHex(buffer); - - in.clear(); - return spanContext; -} - -SpanContext SpanContext::fromStream(std::istream& in, PropagationFormat format) -{ - switch (format) { - case PropagationFormat::JAEGER: - return parseJaegerFormat(in); - case PropagationFormat::W3C: - return parseW3CFormat(in); - } - - return SpanContext(); -} - -SpanContext SpanContext::fromStream(std::istream& in) -{ - return fromStream(in, PropagationFormat::JAEGER); -} - } // namespace jaegertracing diff --git a/src/jaegertracing/SpanContext.h b/src/jaegertracing/SpanContext.h index 663c2cb1..117b36d8 100644 --- a/src/jaegertracing/SpanContext.h +++ b/src/jaegertracing/SpanContext.h @@ -27,19 +27,17 @@ #include #include "jaegertracing/Compilers.h" + #include "jaegertracing/TraceID.h" -#include "jaegertracing/propagation/Format.h" namespace jaegertracing { class SpanContext : public opentracing::SpanContext { public: using StrMap = std::unordered_map; - using PropagationFormat = propagation::Format; enum class Flag : unsigned char { kSampled = 1, kDebug = 2 }; - static SpanContext fromStream(std::istream& in, PropagationFormat format); static SpanContext fromStream(std::istream& in); SpanContext() @@ -146,13 +144,13 @@ class SpanContext : public opentracing::SpanContext { const std::string& debugID() const { return _debugID; } - const std::string& traceState() const { return _traceState; } - bool isSampled() const { return _flags & static_cast(Flag::kSampled); } + const std::string& traceState() const { return _traceState; } + bool isDebug() const { return _flags & static_cast(Flag::kDebug); @@ -165,32 +163,12 @@ class SpanContext : public opentracing::SpanContext { bool isValid() const { return _traceID.isValid() && _spanID != 0; } - template - void print(Stream& out, PropagationFormat format) const - { - switch (format) { - case PropagationFormat::JAEGER: - _traceID.print(out, PropagationFormat::JAEGER); - out << ':' << std::hex << _spanID << ':' << std::hex << _parentID - << ':' << std::hex << static_cast(_flags); - break; - case PropagationFormat::W3C: - out << "00"; - out << '-'; - _traceID.print(out, PropagationFormat::W3C); - out << '-'; - out << std::setw(16) << std::setfill('0') << std::hex << _spanID; - out << '-'; - out << std::setw(2) << std::setfill('0') << std::hex - << static_cast(_flags); - break; - } - } - template void print(Stream& out) const { - print(out, PropagationFormat::JAEGER); + _traceID.print(out); + out << ':' << std::hex << _spanID << ':' << std::hex << _parentID << ':' + << std::hex << static_cast(_flags); } void ForeachBaggageItem( @@ -229,9 +207,6 @@ class SpanContext : public opentracing::SpanContext { } private: - static SpanContext parseJaegerFormat(std::istream& in); - static SpanContext parseW3CFormat(std::istream& in); - TraceID _traceID; uint64_t _spanID; uint64_t _parentID; diff --git a/src/jaegertracing/SpanContextTest.cpp b/src/jaegertracing/SpanContextTest.cpp index f9d41e2f..6eef6b3c 100644 --- a/src/jaegertracing/SpanContextTest.cpp +++ b/src/jaegertracing/SpanContextTest.cpp @@ -24,8 +24,6 @@ namespace jaegertracing { namespace { -using PropagationFormat = propagation::Format; - struct FromStreamTestCase { std::string _input; bool _success; @@ -33,7 +31,7 @@ struct FromStreamTestCase { } // anonymous namespace -TEST(SpanContext, testFromStreamWithJaegerFormat) +TEST(SpanContext, testFromStream) { const FromStreamTestCase testCases[] = { { "", false }, @@ -59,7 +57,7 @@ TEST(SpanContext, testFromStreamWithJaegerFormat) { std::stringstream ss; ss << testCase._input; - spanContext = SpanContext::fromStream(ss, PropagationFormat::JAEGER); + spanContext = SpanContext::fromStream(ss); ASSERT_EQ(testCase._success, spanContext.isValid()) << "input=" << testCase._input; } @@ -75,67 +73,12 @@ TEST(SpanContext, testFromStreamWithJaegerFormat) } } -TEST(SpanContext, testFromStreamWithW3CFormat) -{ - const FromStreamTestCase testCases[] = { - { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", true }, - { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-00", true }, - { "00-11111111111111111111111111111111-2222222222222222-01", true }, - { "00-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-BBBBBBBBBBBBBBBB-01", true }, - { "", false }, - { "000af7651916cd43dd8448eb211c80319cb9c7c989f97918e101", false }, - { "000af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "00-0af7651916cd43dd8448eb211c80319cb9c7c989f97918e1-01", false }, - { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e101", false }, - { "000af7651916cd43dd8448eb211c80319cb9c7c989f97918e1-01", false }, - { "00-0af7651916cd43dd8448eb211c80319cb9c7c989f97918e101", false }, - { "01-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "000-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "0k-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "k0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, - { "00-00000000000000000000000000000000-b9c7c989f97918e1-01", false }, - { "01-0af7651916cd43dd8448eb211c80319-b9c7c989f97918e1-01", false }, - { "01-0af7651916cd43dd8448eb211c80319cc-b9c7c989f97918e1-01", false }, - { "00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01", false } - }; - - for (auto&& testCase : testCases) { - SpanContext spanContext; - { - std::stringstream ss; - ss << testCase._input; - spanContext = SpanContext::fromStream(ss, PropagationFormat::W3C); - ASSERT_EQ(testCase._success, spanContext.isValid()) - << "input=" << testCase._input; - } - } -} - -TEST(SpanContext, testJaegerFormatting) -{ - SpanContext spanContext(TraceID(255, 1), 2, 3, 1, SpanContext::StrMap()); - { - std::ostringstream oss; - spanContext.print(oss, PropagationFormat::JAEGER); - ASSERT_EQ("ff0000000000000001:2:3:1", oss.str()); - } - { - std::ostringstream oss; - oss << spanContext; - ASSERT_EQ("ff0000000000000001:2:3:1", oss.str()); - } -} - -TEST(SpanContext, testW3CFormatting) +TEST(SpanContext, testFormatting) { - SpanContext spanContext(TraceID(255, 1), 2, 3, 1, SpanContext::StrMap()); + SpanContext spanContext(TraceID(255, 255), 0, 0, 0, SpanContext::StrMap()); std::ostringstream oss; - spanContext.print(oss, PropagationFormat::W3C); - ASSERT_EQ("00-00000000000000ff0000000000000001-0000000000000002-01", - oss.str()); + oss << spanContext; + ASSERT_EQ("ff00000000000000ff:0:0:0", oss.str()); } TEST(SpanContext, testBaggage) diff --git a/src/jaegertracing/TraceID.cpp b/src/jaegertracing/TraceID.cpp index 107aaeb6..59a5ceb4 100644 --- a/src/jaegertracing/TraceID.cpp +++ b/src/jaegertracing/TraceID.cpp @@ -22,7 +22,7 @@ namespace jaegertracing { -TraceID TraceID::parseJaegerFormat(std::istream& in) +TraceID TraceID::fromStream(std::istream& in) { TraceID traceID; constexpr auto kMaxChars = static_cast(32); @@ -46,40 +46,4 @@ TraceID TraceID::parseJaegerFormat(std::istream& in) return traceID; } -TraceID TraceID::parseW3CFormat(std::istream& in) -{ - TraceID traceID; - constexpr auto kMaxChars = static_cast(32); - auto buffer = utils::HexParsing::readSegment(in, kMaxChars, '-'); - - if (buffer.empty() || buffer.size() != kMaxChars) { - return TraceID(); - } - - auto beginLowStr = std::end(buffer) - kMaxChars / 2; - const std::string highStr(std::begin(buffer), beginLowStr); - traceID._high = utils::HexParsing::decodeHex(highStr); - const std::string lowStr(beginLowStr, std::end(buffer)); - traceID._low = utils::HexParsing::decodeHex(lowStr); - - return traceID; -} - -TraceID TraceID::fromStream(std::istream& in, PropagationFormat format) -{ - switch (format) { - case PropagationFormat::JAEGER: - return parseJaegerFormat(in); - case PropagationFormat::W3C: - return parseW3CFormat(in); - } - - return TraceID(); -} - -TraceID TraceID::fromStream(std::istream& in) -{ - return fromStream(in, PropagationFormat::JAEGER); -} - } // namespace jaegertracing diff --git a/src/jaegertracing/TraceID.h b/src/jaegertracing/TraceID.h index e25f7bbf..867f0c29 100644 --- a/src/jaegertracing/TraceID.h +++ b/src/jaegertracing/TraceID.h @@ -21,15 +21,10 @@ #include #include -#include "jaegertracing/propagation/Format.h" - namespace jaegertracing { class TraceID { public: - using PropagationFormat = propagation::Format; - - static TraceID fromStream(std::istream& in, PropagationFormat format); static TraceID fromStream(std::istream& in); TraceID() @@ -45,30 +40,16 @@ class TraceID { bool isValid() const { return _high != 0 || _low != 0; } - template - void print(Stream& out, PropagationFormat format) const - { - switch (format) { - case PropagationFormat::JAEGER: - if (_high == 0) { - out << std::hex << _low; - } - else { - out << std::hex << _high << std::setw(16) << std::setfill('0') - << std::hex << _low; - } - break; - case PropagationFormat::W3C: - out << std::setw(16) << std::setfill('0') << std::hex << _high; - out << std::setw(16) << std::setfill('0') << std::hex << _low; - break; - } - } - template void print(Stream& out) const { - print(out, PropagationFormat::JAEGER); + if (_high == 0) { + out << std::hex << _low; + } + else { + out << std::hex << _high << std::setw(16) << std::setfill('0') + << std::hex << _low; + } } uint64_t high() const { return _high; } @@ -81,9 +62,6 @@ class TraceID { } private: - static TraceID parseJaegerFormat(std::istream& in); - static TraceID parseW3CFormat(std::istream& in); - uint64_t _high; uint64_t _low; }; diff --git a/src/jaegertracing/TraceIDTest.cpp b/src/jaegertracing/TraceIDTest.cpp index db690e72..ece21cfe 100644 --- a/src/jaegertracing/TraceIDTest.cpp +++ b/src/jaegertracing/TraceIDTest.cpp @@ -20,36 +20,11 @@ namespace jaegertracing { -using PropagationFormat = propagation::Format; - -TEST(TraceID, testPrintJaegerFormat) +TEST(TraceID, testPrint) { std::ostringstream oss; - TraceID(0, 10).print(oss, PropagationFormat::JAEGER); + oss << TraceID(0, 10); ASSERT_EQ("a", oss.str()); } -TEST(TraceID, testPrintW3CFormat) -{ - std::ostringstream oss; - TraceID(0, 10).print(oss, PropagationFormat::W3C); - ASSERT_EQ("0000000000000000000000000000000a", oss.str()); -} - -TEST(TraceID, testfromStreamJaegerFormat) -{ - std::stringstream ss; - ss << "a"; - auto traceID = TraceID::fromStream(ss, PropagationFormat::JAEGER); - ASSERT_EQ(TraceID(0, 10), traceID); -} - -TEST(TraceID, testfromStreamW3CFormat) -{ - std::stringstream ss; - ss << "0000000000000000000000000000000a"; - auto traceID = TraceID::fromStream(ss, PropagationFormat::JAEGER); - ASSERT_EQ(TraceID(0, 10), traceID); -} - } // namespace jaegertracing diff --git a/src/jaegertracing/Tracer.cpp b/src/jaegertracing/Tracer.cpp index b6037c00..ece94b51 100644 --- a/src/jaegertracing/Tracer.cpp +++ b/src/jaegertracing/Tracer.cpp @@ -18,6 +18,8 @@ #include "jaegertracing/Tracer.h" #include "jaegertracing/Reference.h" #include "jaegertracing/TraceID.h" +#include "jaegertracing/propagation/JaegerPropagator.h" +#include "jaegertracing/propagation/W3CPropagator.h" #include "jaegertracing/samplers/SamplingStatus.h" #include #include @@ -258,6 +260,22 @@ Tracer::make(const std::string& serviceName, } auto metrics = std::make_shared(statsFactory); + + TextMapPropagator* textPropagator; + HTTPHeaderPropagator* httpHeaderPropagator; + if (config.propagationFormat() == propagation::Format::W3C) { + textPropagator = + new propagation::W3CTextMapPropagator(config.headers(), metrics); + httpHeaderPropagator = + new propagation::W3CHTTPHeaderPropagator(config.headers(), metrics); + } + else { + textPropagator = + new propagation::JaegerTextMapPropagator(config.headers(), metrics); + httpHeaderPropagator = new propagation::JaegerHTTPHeaderPropagator( + config.headers(), metrics); + } + std::shared_ptr sampler( config.sampler().makeSampler(serviceName, *logger, *metrics)); std::shared_ptr reporter( @@ -267,7 +285,8 @@ Tracer::make(const std::string& serviceName, reporter, logger, metrics, - config.headers(), + textPropagator, + httpHeaderPropagator, config.tags(), options)); } diff --git a/src/jaegertracing/Tracer.h b/src/jaegertracing/Tracer.h index 8d204267..52709f3f 100644 --- a/src/jaegertracing/Tracer.h +++ b/src/jaegertracing/Tracer.h @@ -119,7 +119,7 @@ class Tracer : public opentracing::Tracer, return opentracing::make_expected_from_error( opentracing::invalid_span_context_error); } - _textPropagator.inject(*jaegerCtx, writer); + _textPropagator->inject(*jaegerCtx, writer); return opentracing::make_expected(); } @@ -132,7 +132,7 @@ class Tracer : public opentracing::Tracer, return opentracing::make_expected_from_error( opentracing::invalid_span_context_error); } - _httpHeaderPropagator.inject(*jaegerCtx, writer); + _httpHeaderPropagator->inject(*jaegerCtx, writer); return opentracing::make_expected(); } @@ -150,7 +150,7 @@ class Tracer : public opentracing::Tracer, opentracing::expected> Extract(const opentracing::TextMapReader& reader) const override { - const auto spanContext = _textPropagator.extract(reader); + const auto spanContext = _textPropagator->extract(reader); if (spanContext == SpanContext()) { return std::unique_ptr(); } @@ -161,7 +161,7 @@ class Tracer : public opentracing::Tracer, opentracing::expected> Extract(const opentracing::HTTPHeadersReader& reader) const override { - const auto spanContext = _httpHeaderPropagator.extract(reader); + const auto spanContext = _httpHeaderPropagator->extract(reader); if (spanContext == SpanContext()) { return std::unique_ptr(); } @@ -201,12 +201,20 @@ class Tracer : public opentracing::Tracer, } private: + using TextMapPropagator = + propagation::Propagator; + using HTTPHeaderPropagator = + propagation::Propagator; + Tracer(const std::string& serviceName, const std::shared_ptr& sampler, const std::shared_ptr& reporter, const std::shared_ptr& logger, const std::shared_ptr& metrics, - const propagation::HeadersConfig& headersConfig, + const TextMapPropagator* textPropagator, + const HTTPHeaderPropagator* httpHeaderPropagator, const std::vector& tags, int options) : _serviceName(serviceName) @@ -216,8 +224,8 @@ class Tracer : public opentracing::Tracer, , _metrics(metrics) , _logger(logger) , _randomNumberGenerator() - , _textPropagator(headersConfig, _metrics) - , _httpHeaderPropagator(headersConfig, _metrics) + , _textPropagator(textPropagator) + , _httpHeaderPropagator(httpHeaderPropagator) , _binaryPropagator(_metrics) , _tags() , _restrictionManager(new baggage::DefaultRestrictionManager(0)) @@ -294,8 +302,8 @@ class Tracer : public opentracing::Tracer, std::shared_ptr _logger; mutable std::mt19937_64 _randomNumberGenerator; mutable std::mutex _randomMutex; - propagation::TextMapPropagator _textPropagator; - propagation::HTTPHeaderPropagator _httpHeaderPropagator; + std::unique_ptr _textPropagator; + std::unique_ptr _httpHeaderPropagator; propagation::BinaryPropagator _binaryPropagator; std::vector _tags; std::unique_ptr _restrictionManager; diff --git a/src/jaegertracing/TracerTest.cpp b/src/jaegertracing/TracerTest.cpp index 64a0e923..a532c063 100644 --- a/src/jaegertracing/TracerTest.cpp +++ b/src/jaegertracing/TracerTest.cpp @@ -477,7 +477,8 @@ TEST(Tracer, testPropagationWithW3CHeaderAndFormat) oss << "00"; oss << '-'; oss << std::setw(16) << std::setfill('0') << std::hex - << spanContext.traceID().high() << std::hex + << spanContext.traceID().high(); + oss << std::setw(16) << std::setfill('0') << std::hex << spanContext.traceID().low(); oss << '-'; oss << std::setw(16) << std::setfill('0') << std::hex @@ -490,7 +491,7 @@ TEST(Tracer, testPropagationWithW3CHeaderAndFormat) ASSERT_TRUE( static_cast(tracer->Inject(span->context(), headerWriter))); ASSERT_EQ(1, headerMap.size()); - ASSERT_EQ(oss.str(), headerMap.at(kW3CTraceContextHeaderName)); + ASSERT_EQ(oss.str(), headerMap.at(kW3CTraceParentHeaderName)); ReaderMock headerReader(headerMap); auto result = tracer->Extract(headerReader); @@ -510,7 +511,7 @@ TEST(Tracer, testPropagationWithW3CTraceState) const auto tracer = std::static_pointer_cast(opentracing::Tracer::Global()); StrMap headerMap{ - { kW3CTraceContextHeaderName, + { kW3CTraceParentHeaderName, "00-00000000000000000000000000000001-0000000000000001-01" }, { kW3CTraceStateHeaderName, "foo=bar" } }; diff --git a/src/jaegertracing/propagation/HeadersConfig.h b/src/jaegertracing/propagation/HeadersConfig.h index 3d7a9fc5..4ae21355 100644 --- a/src/jaegertracing/propagation/HeadersConfig.h +++ b/src/jaegertracing/propagation/HeadersConfig.h @@ -18,8 +18,6 @@ #define JAEGERTRACING_PROPAGATION_HEADERSCONFIG_H #include "jaegertracing/Constants.h" -#include "jaegertracing/propagation/Format.h" -#include "jaegertracing/utils/EnvVariable.h" #include "jaegertracing/utils/YAML.h" #include @@ -28,9 +26,6 @@ namespace propagation { class HeadersConfig { public: - - static constexpr auto kJAEGER_PROPAGATION_ENV_PROP = "JAEGER_PROPAGATION"; - #ifdef JAEGERTRACING_WITH_YAML_CPP static HeadersConfig parse(const YAML::Node& configYAML) @@ -50,26 +45,17 @@ class HeadersConfig { const auto traceBaggageHeaderPrefix = utils::yaml::findOrDefault( configYAML, "traceBaggageHeaderPrefix", ""); - const auto traceStateHeaderName = - utils::yaml::findOrDefault( - configYAML, "TraceStateHeaderName", ""); - const auto traceContextHeaderFormat = - utils::yaml::findOrDefault( - configYAML, "TraceContextHeaderFormat", ""); - - return HeadersConfig( - jaegerDebugHeader, - jaegerBaggageHeader, - traceContextHeaderName, - traceBaggageHeaderPrefix, - traceStateHeaderName, - traceContextHeaderFormat == "w3c" ? Format::W3C : Format::JAEGER); + + return HeadersConfig(jaegerDebugHeader, + jaegerBaggageHeader, + traceContextHeaderName, + traceBaggageHeaderPrefix); } #endif // JAEGERTRACING_WITH_YAML_CPP HeadersConfig() - : HeadersConfig("", "", "", "", "", Format::JAEGER) + : HeadersConfig("", "", "", "") { } @@ -88,35 +74,6 @@ class HeadersConfig { , _traceBaggageHeaderPrefix(traceBaggageHeaderPrefix.empty() ? kTraceBaggageHeaderPrefix : traceBaggageHeaderPrefix) - , _traceContextHeaderFormat(Format::JAEGER) - { - } - - HeadersConfig(const std::string& jaegerDebugHeader, - const std::string& jaegerBaggageHeader, - const std::string& traceContextHeaderName, - const std::string& traceBaggageHeaderPrefix, - const std::string& traceStateHeaderName, - Format traceContextHeaderFormat) - : _jaegerDebugHeader(jaegerDebugHeader.empty() ? kJaegerDebugHeader - : jaegerDebugHeader) - , _jaegerBaggageHeader(jaegerBaggageHeader.empty() - ? kJaegerBaggageHeader - : jaegerBaggageHeader) - , _traceContextHeaderName(traceContextHeaderName.empty() - ? (traceContextHeaderFormat == Format::W3C - ? kW3CTraceContextHeaderName - : kTraceContextHeaderName) - : traceContextHeaderName) - , _traceBaggageHeaderPrefix(traceBaggageHeaderPrefix.empty() - ? kTraceBaggageHeaderPrefix - : traceBaggageHeaderPrefix) - , _traceStateHeaderName(traceStateHeaderName.empty() - ? (traceContextHeaderFormat == Format::W3C - ? kW3CTraceStateHeaderName - : "") - : traceStateHeaderName) - , _traceContextHeaderFormat(traceContextHeaderFormat) { } @@ -137,40 +94,11 @@ class HeadersConfig { return _traceContextHeaderName; } - const std::string& traceStateHeaderName() const - { - return _traceStateHeaderName; - } - - Format traceContextHeaderFormat() const - { - return _traceContextHeaderFormat; - } - - void fromEnv() - { - const auto propagationFormat = - utils::EnvVariable::getStringVariable(kJAEGER_PROPAGATION_ENV_PROP); - if (!propagationFormat.empty()) { - if (propagationFormat == "jaeger") { - _traceContextHeaderName = kTraceContextHeaderName; - _traceContextHeaderFormat = Format::JAEGER; - } - else if (propagationFormat == "w3c") { - _traceContextHeaderName = kW3CTraceContextHeaderName; - _traceStateHeaderName = kW3CTraceStateHeaderName; - _traceContextHeaderFormat = Format::W3C; - } - } - } - private: std::string _jaegerDebugHeader; std::string _jaegerBaggageHeader; std::string _traceContextHeaderName; std::string _traceBaggageHeaderPrefix; - std::string _traceStateHeaderName; - Format _traceContextHeaderFormat; }; } // namespace propagation diff --git a/src/jaegertracing/propagation/JaegerPropagator.cpp b/src/jaegertracing/propagation/JaegerPropagator.cpp new file mode 100644 index 00000000..fa13d67f --- /dev/null +++ b/src/jaegertracing/propagation/JaegerPropagator.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jaegertracing/propagation/JaegerPropagator.h" diff --git a/src/jaegertracing/propagation/JaegerPropagator.h b/src/jaegertracing/propagation/JaegerPropagator.h new file mode 100644 index 00000000..abe882ef --- /dev/null +++ b/src/jaegertracing/propagation/JaegerPropagator.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2020 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JAEGERTRACING_PROPAGATION_JAEGERPROPAGATOR_H +#define JAEGERTRACING_PROPAGATION_JAEGERPROPAGATOR_H + +#include "jaegertracing/propagation/propagator.h" + +namespace jaegertracing { +namespace propagation { + +template +class JaegerPropagator : public Propagator { + public: + using Reader = ReaderType; + using Writer = WriterType; + using StrMap = SpanContext::StrMap; + + using Propagator::Propagator; + + protected: + SpanContext doExtract(const Reader& reader) const override + { + SpanContext ctx; + StrMap baggage; + const auto result = + reader.ForeachKey([this, &ctx, &baggage](const std::string& rawKey, + const std::string& value) { + const auto key = this->normalizeKey(rawKey); + if (key == this->_headerKeys.traceContextHeaderName()) { + const auto safeValue = this->decodeValue(value); + std::istringstream iss(safeValue); + if (!(iss >> ctx) || ctx == SpanContext()) { + return opentracing::make_expected_from_error( + opentracing::span_context_corrupted_error); + } + } + else if (key == this->_headerKeys.jaegerBaggageHeader()) { + for (auto&& pair : parseCommaSeparatedMap(value)) { + baggage[pair.first] = pair.second; + } + } + else { + const auto prefix = + this->_headerKeys.traceBaggageHeaderPrefix(); + if (key.size() >= prefix.size() && + key.substr(0, prefix.size()) == prefix) { + const auto safeKey = removeBaggageKeyPrefix(key); + const auto safeValue = this->decodeValue(value); + baggage[safeKey] = safeValue; + } + } + + return opentracing::make_expected(); + }); + + if (!result && + result.error() == opentracing::span_context_corrupted_error) { + this->_metrics->decodingErrors().inc(1); + return SpanContext(); + } + + return SpanContext( + ctx.traceID(), ctx.spanID(), ctx.parentID(), ctx.flags(), baggage); + } + + void doInject(const SpanContext& ctx, const Writer& writer) const override + { + std::ostringstream oss; + oss << ctx; + writer.Set(this->_headerKeys.traceContextHeaderName(), oss.str()); + ctx.forEachBaggageItem( + [this, &writer](const std::string& key, const std::string& value) { + const auto safeKey = addBaggageKeyPrefix(key); + const auto safeValue = this->encodeValue(value); + writer.Set(safeKey, safeValue); + return true; + }); + } + + private: + static StrMap parseCommaSeparatedMap(const std::string& escapedValue) + { + StrMap map; + std::istringstream iss(net::URI::queryUnescape(escapedValue)); + std::string piece; + while (std::getline(iss, piece, ',')) { + const auto eqPos = piece.find('='); + if (eqPos != std::string::npos) { + const auto key = piece.substr(0, eqPos); + const auto value = piece.substr(eqPos + 1); + map[key] = value; + } + } + return map; + } + + std::string addBaggageKeyPrefix(const std::string& key) const + { + return this->_headerKeys.traceBaggageHeaderPrefix() + key; + } + + std::string removeBaggageKeyPrefix(const std::string& key) const + { + return key.substr(this->_headerKeys.traceBaggageHeaderPrefix().size()); + } +}; + +using JaegerTextMapPropagator = + JaegerPropagator; + +class JaegerHTTPHeaderPropagator + : public JaegerPropagator { + public: + using JaegerPropagator::JaegerPropagator; + + protected: + std::string encodeValue(const std::string& str) const override + { + return net::URI::queryEscape(str); + } + + std::string decodeValue(const std::string& str) const override + { + return net::URI::queryUnescape(str); + } + + std::string normalizeKey(const std::string& rawKey) const override + { + std::string key; + key.reserve(rawKey.size()); + std::transform(std::begin(rawKey), + std::end(rawKey), + std::back_inserter(key), + [](char ch) { return std::tolower(ch); }); + return key; + } +}; + +} // namespace propagation +} // namespace jaegertracing + +#endif // JAEGERTRACING_PROPAGATION_JAEGERPROPAGATOR_H diff --git a/src/jaegertracing/propagation/Propagator.h b/src/jaegertracing/propagation/Propagator.h index 840e69d3..1d785c47 100644 --- a/src/jaegertracing/propagation/Propagator.h +++ b/src/jaegertracing/propagation/Propagator.h @@ -40,7 +40,6 @@ class Propagator : public Extractor, public Injector { public: using Reader = ReaderType; using Writer = WriterType; - using StrMap = SpanContext::StrMap; Propagator() : _headerKeys() @@ -59,54 +58,21 @@ class Propagator : public Extractor, public Injector { SpanContext extract(const Reader& reader) const override { - SpanContext ctx; - StrMap baggage; std::string debugID; - std::string traceState; - const auto result = reader.ForeachKey( - [this, &ctx, &debugID, &baggage, &traceState]( - const std::string& rawKey, const std::string& value) { + const auto result = + reader.ForeachKey([this, &debugID](const std::string& rawKey, + const std::string& value) { const auto key = normalizeKey(rawKey); - if (key == _headerKeys.traceContextHeaderName()) { - const auto safeValue = decodeValue(value); - std::istringstream iss(safeValue); - ctx = SpanContext::fromStream( - iss, _headerKeys.traceContextHeaderFormat()); - if (!iss || ctx == SpanContext()) { - return opentracing::make_expected_from_error( - opentracing::span_context_corrupted_error); - } - } - else if (key == _headerKeys.jaegerDebugHeader()) { + if (key == _headerKeys.jaegerDebugHeader()) { debugID = value; } - else if (key == _headerKeys.jaegerBaggageHeader()) { - for (auto&& pair : parseCommaSeparatedMap(value)) { - baggage[pair.first] = pair.second; - } - } - else if (key == _headerKeys.traceStateHeaderName()) { - traceState = value; - } - else { - const auto prefix = _headerKeys.traceBaggageHeaderPrefix(); - if (key.size() >= prefix.size() && - key.substr(0, prefix.size()) == prefix) { - const auto safeKey = removeBaggageKeyPrefix(key); - const auto safeValue = decodeValue(value); - baggage[safeKey] = safeValue; - } - } + return opentracing::make_expected(); }); - if (!result && - result.error() == opentracing::span_context_corrupted_error) { - _metrics->decodingErrors().inc(1); - return SpanContext(); - } - - if (!ctx.traceID().isValid() && debugID.empty() && baggage.empty()) { + SpanContext ctx = doExtract(reader); + if (!ctx.traceID().isValid() && ctx.baggage().empty() && + debugID.empty()) { return SpanContext(); } @@ -119,30 +85,21 @@ class Propagator : public Extractor, public Injector { ctx.spanID(), ctx.parentID(), flags, - baggage, + ctx.baggage(), debugID, - traceState); + ctx.traceState()); } void inject(const SpanContext& ctx, const Writer& writer) const override { - std::ostringstream oss; - ctx.print(oss, _headerKeys.traceContextHeaderFormat()); - writer.Set(_headerKeys.traceContextHeaderName(), oss.str()); - ctx.forEachBaggageItem( - [this, &writer](const std::string& key, const std::string& value) { - const auto safeKey = addBaggageKeyPrefix(key); - const auto safeValue = encodeValue(value); - writer.Set(safeKey, safeValue); - return true; - }); - if (!_headerKeys.traceStateHeaderName().empty() && - !ctx.traceState().empty()) { - writer.Set(_headerKeys.traceStateHeaderName(), ctx.traceState()); - } + doInject(ctx, writer); } protected: + virtual SpanContext doExtract(const Reader& reader) const = 0; + + virtual void doInject(const SpanContext& ctx, const Writer& writer) const = 0; + virtual std::string encodeValue(const std::string& str) const { return str; @@ -158,69 +115,10 @@ class Propagator : public Extractor, public Injector { return rawKey; } - private: - static StrMap parseCommaSeparatedMap(const std::string& escapedValue) - { - StrMap map; - std::istringstream iss(net::URI::queryUnescape(escapedValue)); - std::string piece; - while (std::getline(iss, piece, ',')) { - const auto eqPos = piece.find('='); - if (eqPos != std::string::npos) { - const auto key = piece.substr(0, eqPos); - const auto value = piece.substr(eqPos + 1); - map[key] = value; - } - } - return map; - } - - std::string addBaggageKeyPrefix(const std::string& key) const - { - return _headerKeys.traceBaggageHeaderPrefix() + key; - } - - std::string removeBaggageKeyPrefix(const std::string& key) const - { - return key.substr(_headerKeys.traceBaggageHeaderPrefix().size()); - } - HeadersConfig _headerKeys; std::shared_ptr _metrics; }; -using TextMapPropagator = Propagator; - -class HTTPHeaderPropagator - : public Propagator { - public: - using Propagator::Propagator; - - protected: - std::string encodeValue(const std::string& str) const override - { - return net::URI::queryEscape(str); - } - - std::string decodeValue(const std::string& str) const override - { - return net::URI::queryUnescape(str); - } - - std::string normalizeKey(const std::string& rawKey) const override - { - std::string key; - key.reserve(rawKey.size()); - std::transform(std::begin(rawKey), - std::end(rawKey), - std::back_inserter(key), - [](char ch) { return std::tolower(ch); }); - return key; - } -}; - class BinaryPropagator : public Extractor, public Injector { public: diff --git a/src/jaegertracing/propagation/W3CPropagator.cpp b/src/jaegertracing/propagation/W3CPropagator.cpp new file mode 100644 index 00000000..2562e9cd --- /dev/null +++ b/src/jaegertracing/propagation/W3CPropagator.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jaegertracing/propagation/W3CPropagator.h" diff --git a/src/jaegertracing/propagation/W3CPropagator.h b/src/jaegertracing/propagation/W3CPropagator.h new file mode 100644 index 00000000..81e56327 --- /dev/null +++ b/src/jaegertracing/propagation/W3CPropagator.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JAEGERTRACING_PROPAGATION_W3CPROPAGATOR_H +#define JAEGERTRACING_PROPAGATION_W3CPROPAGATOR_H + +#include "jaegertracing/propagation/propagator.h" +#include "jaegertracing/utils/HexParsing.h" + +namespace jaegertracing { +namespace propagation { + +template +class W3CPropagator : public Propagator { + public: + using Reader = ReaderType; + using Writer = WriterType; + using StrMap = SpanContext::StrMap; + + using Propagator::Propagator; + + protected: + SpanContext doExtract(const Reader& reader) const override + { + SpanContext ctx; + std::string traceState; + const auto result = reader.ForeachKey( + [this, &ctx, &traceState](const std::string& rawKey, + const std::string& value) { + const auto key = this->normalizeKey(rawKey); + if (key == kW3CTraceParentHeaderName) { + const auto safeValue = this->decodeValue(value); + std::istringstream iss(safeValue); + ctx = readTraceParent(iss); + if (!iss || ctx == SpanContext()) { + return opentracing::make_expected_from_error( + opentracing::span_context_corrupted_error); + } + } + else if (key == kW3CTraceStateHeaderName) { + traceState = this->decodeValue(value); + } + + return opentracing::make_expected(); + }); + + if (!result && + result.error() == opentracing::span_context_corrupted_error) { + this->_metrics->decodingErrors().inc(1); + return SpanContext(); + } + + return SpanContext(ctx.traceID(), + ctx.spanID(), + ctx.parentID(), + ctx.flags(), + StrMap(), + "", + traceState); + } + + void doInject(const SpanContext& ctx, const Writer& writer) const override + { + std::ostringstream oss; + writeTraceParent(oss, ctx); + writer.Set(kW3CTraceParentHeaderName, oss.str()); + if (!ctx.traceState().empty()) { + writer.Set(kW3CTraceStateHeaderName, ctx.traceState()); + } + } + + private: + SpanContext readTraceParent(std::istream& in) const + { + char ch = '\0'; + if (!in.get(ch) || ch != '0') { + return SpanContext(); + } + + if (!in.get(ch) || ch != '0') { + return SpanContext(); + } + + if (!in.get(ch) || ch != '-') { + return SpanContext(); + } + + auto traceID = readTraceID(in); + if (!traceID.isValid()) { + return SpanContext(); + } + + if (!in.get(ch) || ch != '-') { + return SpanContext(); + } + + constexpr auto kMaxUInt64Chars = static_cast(16); + auto buffer = utils::HexParsing::readSegment(in, kMaxUInt64Chars, '-'); + if (buffer.empty()) { + return SpanContext(); + } + auto spanID = utils::HexParsing::decodeHex(buffer); + + if (!in.get(ch) || ch != '-') { + return SpanContext(); + } + + constexpr auto kMaxByteChars = static_cast(2); + buffer = utils::HexParsing::readSegment(in, kMaxByteChars, '-'); + if (buffer.empty() || buffer.size() != 2) { + return SpanContext(); + } + auto flags = utils::HexParsing::decodeHex(buffer); + + in.clear(); + + return SpanContext(traceID, spanID, 0, flags, StrMap()); + } + + TraceID readTraceID(std::istream& in) const + { + TraceID traceID; + constexpr auto kMaxChars = static_cast(32); + auto buffer = utils::HexParsing::readSegment(in, kMaxChars, '-'); + + if (buffer.empty() || buffer.size() != kMaxChars) { + return TraceID(); + } + + auto beginLowStr = std::end(buffer) - kMaxChars / 2; + const std::string highStr(std::begin(buffer), beginLowStr); + auto high = utils::HexParsing::decodeHex(highStr); + const std::string lowStr(beginLowStr, std::end(buffer)); + auto low = utils::HexParsing::decodeHex(lowStr); + + return TraceID(high, low); + } + + void writeTraceParent(std::ostream& out, const SpanContext& ctx) const + { + out << "00"; + out << '-'; + writeTraceID(out, ctx.traceID()); + out << '-'; + out << std::setw(16) << std::setfill('0') << std::hex << ctx.spanID(); + out << '-'; + out << std::setw(2) << std::setfill('0') << std::hex + << static_cast(ctx.flags()); + } + + void writeTraceID(std::ostream& out, const TraceID& traceID) const + { + out << std::setw(16) << std::setfill('0') << std::hex << traceID.high(); + out << std::setw(16) << std::setfill('0') << std::hex << traceID.low(); + } +}; + +using W3CTextMapPropagator = W3CPropagator; + +class W3CHTTPHeaderPropagator + : public W3CPropagator { + public: + using W3CPropagator::W3CPropagator; + + protected: + std::string encodeValue(const std::string& str) const override + { + return net::URI::queryEscape(str); + } + + std::string decodeValue(const std::string& str) const override + { + return net::URI::queryUnescape(str); + } + + std::string normalizeKey(const std::string& rawKey) const override + { + std::string key; + key.reserve(rawKey.size()); + std::transform(std::begin(rawKey), + std::end(rawKey), + std::back_inserter(key), + [](char ch) { return std::tolower(ch); }); + return key; + } +}; + +} // namespace propagation +} // namespace jaegertracing + +#endif // JAEGERTRACING_PROPAGATION_W3CPROPAGATOR_H diff --git a/src/jaegertracing/propagation/W3CPropagatorTest.cpp b/src/jaegertracing/propagation/W3CPropagatorTest.cpp new file mode 100644 index 00000000..9708966d --- /dev/null +++ b/src/jaegertracing/propagation/W3CPropagatorTest.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2020 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jaegertracing/propagation/W3CPropagator.h" +#include + +namespace jaegertracing { +namespace propagation { + +using StrMap = std::unordered_map; + +template +struct WriterMock : public BaseWriter { + explicit WriterMock(StrMap& keyValuePairs) + : _keyValuePairs(keyValuePairs) + { + } + + opentracing::expected + Set(opentracing::string_view key, + opentracing::string_view value) const override + { + _keyValuePairs[key] = value; + return opentracing::make_expected(); + } + + StrMap& _keyValuePairs; +}; + +template +struct ReaderMock : public BaseReader { + using Function = + std::function; + + explicit ReaderMock(const StrMap& keyValuePairs) + : _keyValuePairs(keyValuePairs) + { + } + + opentracing::expected ForeachKey( + std::function(opentracing::string_view, + opentracing::string_view)> f) + const override + { + for (auto&& pair : _keyValuePairs) { + const auto result = f(pair.first, pair.second); + if (!result) { + return result; + } + } + return opentracing::make_expected(); + } + + const StrMap& _keyValuePairs; +}; + +struct ExtractTestCase { + std::string _input; + bool _success; +}; + +TEST(W3CPropagator, testExtract) +{ + const ExtractTestCase testCases[] = { + { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", true }, + { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-00", true }, + { "00-11111111111111111111111111111111-2222222222222222-01", true }, + { "00-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-BBBBBBBBBBBBBBBB-01", true }, + { "", false }, + { "000af7651916cd43dd8448eb211c80319cb9c7c989f97918e101", false }, + { "000af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319cb9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e101", false }, + { "000af7651916cd43dd8448eb211c80319cb9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319cb9c7c989f97918e101", false }, + { "01-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "000-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "0k-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "k0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01", false }, + { "00-00000000000000000000000000000000-b9c7c989f97918e1-01", false }, + { "01-0af7651916cd43dd8448eb211c80319-b9c7c989f97918e1-01", false }, + { "01-0af7651916cd43dd8448eb211c80319cc-b9c7c989f97918e1-01", false }, + { "00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01", false } + }; + + W3CTextMapPropagator textMapPropagator; + W3CHTTPHeaderPropagator httpHeaderPropagator; + for (auto&& testCase : testCases) { + SpanContext spanContext; + { + StrMap map; + map.emplace(kW3CTraceParentHeaderName, testCase._input); + + spanContext = textMapPropagator.extract( + ReaderMock(map)); + ASSERT_EQ(testCase._success, spanContext.isValid()) + << "input=" << testCase._input; + + spanContext = httpHeaderPropagator.extract( + ReaderMock(map)); + ASSERT_EQ(testCase._success, spanContext.isValid()) + << "input=" << testCase._input; + } + } + + StrMap map; + map.emplace(kW3CTraceParentHeaderName, + "00-00000000000000ff0000000000000001-0000000000000002-01"); + map.emplace(kW3CTraceStateHeaderName, "foo=bar"); + + SpanContext spanContext = + textMapPropagator.extract(ReaderMock(map)); + ASSERT_EQ(true, spanContext.isValid()); + ASSERT_EQ("foo=bar", spanContext.traceState()); + + spanContext = httpHeaderPropagator.extract( + ReaderMock(map)); + ASSERT_EQ(true, spanContext.isValid()); + ASSERT_EQ("foo=bar", spanContext.traceState()); +} + +TEST(W3CPropagator, testInject) +{ + SpanContext spanContext( + TraceID(255, 1), 2, 3, 1, SpanContext::StrMap(), "", "foo=bar"); + + StrMap textMap; + WriterMock textMapWriter(textMap); + + W3CTextMapPropagator textMapPropagator; + textMapPropagator.inject(spanContext, textMapWriter); + + ASSERT_EQ("00-00000000000000ff0000000000000001-0000000000000002-01", + textMap.at(kW3CTraceParentHeaderName)); + ASSERT_EQ("foo=bar", textMap.at(kW3CTraceStateHeaderName)); + + StrMap httpHeaderMap; + WriterMock httpHeaderWriter(httpHeaderMap); + + W3CHTTPHeaderPropagator httpHeaderPropagator; + httpHeaderPropagator.inject(spanContext, httpHeaderWriter); + + ASSERT_EQ("00-00000000000000ff0000000000000001-0000000000000002-01", + httpHeaderMap.at(kW3CTraceParentHeaderName)); + ASSERT_EQ("foo=bar", textMap.at(kW3CTraceStateHeaderName)); +} + +} // namespace propagation +} // namespace jaegertracing diff --git a/src/jaegertracing/testutils/TracerUtil.cpp b/src/jaegertracing/testutils/TracerUtil.cpp index 370dfc41..8e649b4a 100644 --- a/src/jaegertracing/testutils/TracerUtil.cpp +++ b/src/jaegertracing/testutils/TracerUtil.cpp @@ -31,7 +31,8 @@ namespace jaegertracing { namespace testutils { namespace TracerUtil { -std::shared_ptr installGlobalTracer(PropagationFormat format) +std::shared_ptr +installGlobalTracer(propagation::Format propagationFormat) { std::unique_ptr handle(new ResourceHandle()); handle->_mockAgent->start(); @@ -49,8 +50,11 @@ std::shared_ptr installGlobalTracer(PropagationFormat format) reporters::Config::Clock::duration(), false, handle->_mockAgent->spanServerAddress().authority()), - propagation::HeadersConfig("", "", "", "", "", format), - baggage::RestrictionsConfig()); + propagation::HeadersConfig("", "", "", ""), + baggage::RestrictionsConfig(), + "", + std::vector(), + propagationFormat); auto tracer = Tracer::make("test-service", config, logging::nullLogger()); opentracing::Tracer::InitGlobal(tracer); @@ -59,7 +63,7 @@ std::shared_ptr installGlobalTracer(PropagationFormat format) std::shared_ptr installGlobalTracer() { - return installGlobalTracer(PropagationFormat::JAEGER); + return installGlobalTracer(propagation::Format::JAEGER); } std::shared_ptr buildTracer(const std::string& endpoint) @@ -68,13 +72,13 @@ std::shared_ptr buildTracer(const std::string& endpoint) Config config( false, samplers::Config("const", - 1, - samplingServerURLStream.str(), - 0, - samplers::Config::Clock::duration()), + 1, + samplingServerURLStream.str(), + 0, + samplers::Config::Clock::duration()), reporters::Config(0, std::chrono::milliseconds(100), - false, "", endpoint), + false, "", endpoint), propagation::HeadersConfig(), baggage::RestrictionsConfig()); diff --git a/src/jaegertracing/testutils/TracerUtil.h b/src/jaegertracing/testutils/TracerUtil.h index 3aa635e2..ab94ed78 100644 --- a/src/jaegertracing/testutils/TracerUtil.h +++ b/src/jaegertracing/testutils/TracerUtil.h @@ -27,8 +27,6 @@ namespace jaegertracing { namespace testutils { namespace TracerUtil { -using PropagationFormat = propagation::Format; - struct ResourceHandle { ResourceHandle() : _mockAgent(testutils::MockAgent::make()) @@ -43,7 +41,7 @@ struct ResourceHandle { std::shared_ptr _mockAgent; }; -std::shared_ptr installGlobalTracer(PropagationFormat format); +std::shared_ptr installGlobalTracer(propagation::Format format); std::shared_ptr installGlobalTracer(); std::shared_ptr buildTracer(const std::string& endpoint); From 96625d47d067a57b5f357a4591f71e5b483b16eb Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Sun, 6 Dec 2020 19:38:38 +0100 Subject: [PATCH 07/10] Fix build Signed-off-by: Tobias Stadler --- src/jaegertracing/propagation/JaegerPropagator.h | 2 +- src/jaegertracing/propagation/W3CPropagator.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jaegertracing/propagation/JaegerPropagator.h b/src/jaegertracing/propagation/JaegerPropagator.h index abe882ef..9efa2cbe 100644 --- a/src/jaegertracing/propagation/JaegerPropagator.h +++ b/src/jaegertracing/propagation/JaegerPropagator.h @@ -17,7 +17,7 @@ #ifndef JAEGERTRACING_PROPAGATION_JAEGERPROPAGATOR_H #define JAEGERTRACING_PROPAGATION_JAEGERPROPAGATOR_H -#include "jaegertracing/propagation/propagator.h" +#include "jaegertracing/propagation/Propagator.h" namespace jaegertracing { namespace propagation { diff --git a/src/jaegertracing/propagation/W3CPropagator.h b/src/jaegertracing/propagation/W3CPropagator.h index 81e56327..4fda5b5a 100644 --- a/src/jaegertracing/propagation/W3CPropagator.h +++ b/src/jaegertracing/propagation/W3CPropagator.h @@ -17,7 +17,7 @@ #ifndef JAEGERTRACING_PROPAGATION_W3CPROPAGATOR_H #define JAEGERTRACING_PROPAGATION_W3CPROPAGATOR_H -#include "jaegertracing/propagation/propagator.h" +#include "jaegertracing/propagation/Propagator.h" #include "jaegertracing/utils/HexParsing.h" namespace jaegertracing { From 5ba17c5c4f8c14e5be41d09838bb2cec3fb91a98 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Mon, 7 Dec 2020 19:26:41 +0100 Subject: [PATCH 08/10] Fix copyright Signed-off-by: Tobias Stadler --- src/jaegertracing/propagation/Format.cpp | 2 +- src/jaegertracing/propagation/Format.h | 2 +- src/jaegertracing/propagation/JaegerPropagator.cpp | 2 +- src/jaegertracing/propagation/JaegerPropagator.h | 2 +- src/jaegertracing/propagation/W3CPropagator.cpp | 2 +- src/jaegertracing/propagation/W3CPropagator.h | 2 +- src/jaegertracing/propagation/W3CPropagatorTest.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/jaegertracing/propagation/Format.cpp b/src/jaegertracing/propagation/Format.cpp index 7d5c4d81..f2e4b103 100644 --- a/src/jaegertracing/propagation/Format.cpp +++ b/src/jaegertracing/propagation/Format.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020 Uber Technologies, Inc. + * Copyright (c) 2020 The Jaeger Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/jaegertracing/propagation/Format.h b/src/jaegertracing/propagation/Format.h index f0b55f6d..cedafb00 100644 --- a/src/jaegertracing/propagation/Format.h +++ b/src/jaegertracing/propagation/Format.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Uber Technologies, Inc. + * Copyright (c) 2020 The Jaeger Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/jaegertracing/propagation/JaegerPropagator.cpp b/src/jaegertracing/propagation/JaegerPropagator.cpp index fa13d67f..35394aea 100644 --- a/src/jaegertracing/propagation/JaegerPropagator.cpp +++ b/src/jaegertracing/propagation/JaegerPropagator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Uber Technologies, Inc. + * Copyright (c) 2020 The Jaeger Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/jaegertracing/propagation/JaegerPropagator.h b/src/jaegertracing/propagation/JaegerPropagator.h index 9efa2cbe..b46bf07d 100644 --- a/src/jaegertracing/propagation/JaegerPropagator.h +++ b/src/jaegertracing/propagation/JaegerPropagator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Uber Technologies, Inc. + * Copyright (c) 2020 The Jaeger Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/jaegertracing/propagation/W3CPropagator.cpp b/src/jaegertracing/propagation/W3CPropagator.cpp index 2562e9cd..bf8fb57c 100644 --- a/src/jaegertracing/propagation/W3CPropagator.cpp +++ b/src/jaegertracing/propagation/W3CPropagator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Uber Technologies, Inc. + * Copyright (c) 2020 The Jaeger Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/jaegertracing/propagation/W3CPropagator.h b/src/jaegertracing/propagation/W3CPropagator.h index 4fda5b5a..a7345fcb 100644 --- a/src/jaegertracing/propagation/W3CPropagator.h +++ b/src/jaegertracing/propagation/W3CPropagator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Uber Technologies, Inc. + * Copyright (c) 2020 The Jaeger Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/jaegertracing/propagation/W3CPropagatorTest.cpp b/src/jaegertracing/propagation/W3CPropagatorTest.cpp index 9708966d..4eb9715a 100644 --- a/src/jaegertracing/propagation/W3CPropagatorTest.cpp +++ b/src/jaegertracing/propagation/W3CPropagatorTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Uber Technologies, Inc. + * Copyright (c) 2020 The Jaeger Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From d0c77a3c1f42b27e89f865070096b18c8b8151f6 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Mon, 7 Dec 2020 19:28:33 +0100 Subject: [PATCH 09/10] Use shared_ptr instead of raw pointer Signed-off-by: Tobias Stadler --- src/jaegertracing/Tracer.cpp | 23 +++++++++++++---------- src/jaegertracing/Tracer.h | 8 ++++---- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/jaegertracing/Tracer.cpp b/src/jaegertracing/Tracer.cpp index ece94b51..72025490 100644 --- a/src/jaegertracing/Tracer.cpp +++ b/src/jaegertracing/Tracer.cpp @@ -261,19 +261,22 @@ Tracer::make(const std::string& serviceName, auto metrics = std::make_shared(statsFactory); - TextMapPropagator* textPropagator; - HTTPHeaderPropagator* httpHeaderPropagator; + std::shared_ptr textPropagator; + std::shared_ptr httpHeaderPropagator; if (config.propagationFormat() == propagation::Format::W3C) { - textPropagator = - new propagation::W3CTextMapPropagator(config.headers(), metrics); - httpHeaderPropagator = - new propagation::W3CHTTPHeaderPropagator(config.headers(), metrics); + textPropagator = std::shared_ptr( + new propagation::W3CTextMapPropagator(config.headers(), metrics)); + httpHeaderPropagator = std::shared_ptr( + new propagation::W3CHTTPHeaderPropagator(config.headers(), + metrics)); } else { - textPropagator = - new propagation::JaegerTextMapPropagator(config.headers(), metrics); - httpHeaderPropagator = new propagation::JaegerHTTPHeaderPropagator( - config.headers(), metrics); + textPropagator = std::shared_ptr( + new propagation::JaegerTextMapPropagator(config.headers(), + metrics)); + httpHeaderPropagator = std::shared_ptr( + new propagation::JaegerHTTPHeaderPropagator(config.headers(), + metrics)); } std::shared_ptr sampler( diff --git a/src/jaegertracing/Tracer.h b/src/jaegertracing/Tracer.h index 52709f3f..e80f0769 100644 --- a/src/jaegertracing/Tracer.h +++ b/src/jaegertracing/Tracer.h @@ -213,8 +213,8 @@ class Tracer : public opentracing::Tracer, const std::shared_ptr& reporter, const std::shared_ptr& logger, const std::shared_ptr& metrics, - const TextMapPropagator* textPropagator, - const HTTPHeaderPropagator* httpHeaderPropagator, + const std::shared_ptr &textPropagator, + const std::shared_ptr &httpHeaderPropagator, const std::vector& tags, int options) : _serviceName(serviceName) @@ -302,8 +302,8 @@ class Tracer : public opentracing::Tracer, std::shared_ptr _logger; mutable std::mt19937_64 _randomNumberGenerator; mutable std::mutex _randomMutex; - std::unique_ptr _textPropagator; - std::unique_ptr _httpHeaderPropagator; + std::shared_ptr _textPropagator; + std::shared_ptr _httpHeaderPropagator; propagation::BinaryPropagator _binaryPropagator; std::vector _tags; std::unique_ptr _restrictionManager; From 43e137607c234d1dbdce977561368bfc47c0c92a Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Sun, 7 Feb 2021 14:33:57 +0100 Subject: [PATCH 10/10] Log unknown propagation formats and fall back to jaeger format Signed-off-by: Tobias Stadler --- src/jaegertracing/Config.cpp | 8 +++++++- src/jaegertracing/Config.h | 20 +++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/jaegertracing/Config.cpp b/src/jaegertracing/Config.cpp index 57a5f437..ef15554e 100644 --- a/src/jaegertracing/Config.cpp +++ b/src/jaegertracing/Config.cpp @@ -34,11 +34,17 @@ void Config::fromEnv() const auto propagationFormat = utils::EnvVariable::getStringVariable(kJAEGER_PROPAGATION_ENV_PROP); - if(!propagationFormat.empty()) { + if (!propagationFormat.empty()) { if (propagationFormat == "w3c") { _propagationFormat = propagation::Format::W3C; } + else if (propagationFormat == "jaeger") { + _propagationFormat = propagation::Format::JAEGER; + } else { + std::cerr << "ERROR: unknown propagation format '" + << propagationFormat + << "', falling back to jaeger propagation format"; _propagationFormat = propagation::Format::JAEGER; } } diff --git a/src/jaegertracing/Config.h b/src/jaegertracing/Config.h index 6e7a67ca..727763a9 100644 --- a/src/jaegertracing/Config.h +++ b/src/jaegertracing/Config.h @@ -50,8 +50,23 @@ class Config { const auto disabled = utils::yaml::findOrDefault(configYAML, "disabled", false); - const auto propagationFormat = utils::yaml::findOrDefault( + + const auto strPropagationFormat = utils::yaml::findOrDefault( configYAML, "propagation_format", "jaeger"); + propagation::Format propagationFormat; + if (strPropagationFormat == "w3c") { + propagationFormat = propagation::Format::W3C; + } + else if (strPropagationFormat == "jaeger") { + propagationFormat = propagation::Format::JAEGER; + } + else { + std::cerr << "ERROR: unknown propagation format '" + << strPropagationFormat + << "', falling back to jaeger propagation format"; + propagationFormat = propagation::Format::JAEGER; + } + const auto samplerNode = configYAML["sampler"]; const auto sampler = samplers::Config::parse(samplerNode); const auto reporterNode = configYAML["reporter"]; @@ -68,8 +83,7 @@ class Config { baggageRestrictions, serviceName, std::vector(), - propagationFormat == "w3c" ? propagation::Format::W3C - : propagation::Format::JAEGER); + propagationFormat); } #endif // JAEGERTRACING_WITH_YAML_CPP