b3_propagation_test.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. #include <gtest/gtest.h>
  4. #include <stdint.h>
  5. #include <map>
  6. #include <string>
  7. #include <utility>
  8. #include "util.h"
  9. #include "opentelemetry/context/context.h"
  10. #include "opentelemetry/context/propagation/text_map_propagator.h"
  11. #include "opentelemetry/context/runtime_context.h"
  12. #include "opentelemetry/nostd/shared_ptr.h"
  13. #include "opentelemetry/nostd/span.h"
  14. #include "opentelemetry/nostd/string_view.h"
  15. #include "opentelemetry/nostd/variant.h"
  16. #include "opentelemetry/trace/default_span.h"
  17. #include "opentelemetry/trace/propagation/b3_propagator.h"
  18. #include "opentelemetry/trace/scope.h"
  19. #include "opentelemetry/trace/span.h"
  20. #include "opentelemetry/trace/span_context.h"
  21. #include "opentelemetry/trace/span_id.h"
  22. #include "opentelemetry/trace/span_metadata.h"
  23. #include "opentelemetry/trace/trace_flags.h"
  24. #include "opentelemetry/trace/trace_id.h"
  25. using namespace opentelemetry;
  26. class TextMapCarrierTest : public context::propagation::TextMapCarrier
  27. {
  28. public:
  29. nostd::string_view Get(nostd::string_view key) const noexcept override
  30. {
  31. auto it = headers_.find(std::string(key));
  32. if (it != headers_.end())
  33. {
  34. return nostd::string_view(it->second);
  35. }
  36. return "";
  37. }
  38. void Set(nostd::string_view key, nostd::string_view value) noexcept override
  39. {
  40. headers_[std::string(key)] = std::string(value);
  41. }
  42. std::map<std::string, std::string> headers_;
  43. };
  44. using MapB3Context = trace::propagation::B3Propagator;
  45. static MapB3Context format = MapB3Context();
  46. using MapB3ContextMultiHeader = trace::propagation::B3PropagatorMultiHeader;
  47. static MapB3ContextMultiHeader formatMultiHeader = MapB3ContextMultiHeader();
  48. TEST(B3PropagationTest, TraceFlagsBufferGeneration)
  49. {
  50. EXPECT_EQ(MapB3Context::TraceFlagsFromHex("0"), trace::TraceFlags());
  51. EXPECT_EQ(MapB3Context::TraceFlagsFromHex("1"), trace::TraceFlags(trace::TraceFlags::kIsSampled));
  52. }
  53. TEST(B3PropagationTest, PropagateInvalidContext)
  54. {
  55. // Do not propagate invalid trace context.
  56. TextMapCarrierTest carrier;
  57. context::Context ctx{
  58. trace::kSpanKey,
  59. nostd::shared_ptr<trace::Span>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
  60. format.Inject(carrier, ctx);
  61. EXPECT_TRUE(carrier.headers_.count("b3") == 0);
  62. }
  63. TEST(B3PropagationTest, ExtractInvalidContext)
  64. {
  65. TextMapCarrierTest carrier;
  66. carrier.headers_ = {{"b3", "00000000000000000000000000000000-0000000000000000-0"}};
  67. context::Context ctx1 = context::Context{};
  68. context::Context ctx2 = format.Extract(carrier, ctx1);
  69. auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
  70. EXPECT_FALSE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
  71. }
  72. TEST(B3PropagationTest, DoNotOverwriteContextWithInvalidSpan)
  73. {
  74. TextMapCarrierTest carrier;
  75. constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
  76. constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
  77. trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
  78. trace::TraceFlags{true}, false};
  79. nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
  80. // Make sure this invalid span does not overwrite the active span context
  81. carrier.headers_ = {{"b3", "00000000000000000000000000000000-0000000000000000-0"}};
  82. context::Context ctx1{trace::kSpanKey, sp};
  83. context::Context ctx2 = format.Extract(carrier, ctx1);
  84. auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
  85. auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
  86. EXPECT_EQ(Hex(span->GetContext().trace_id()), "0102030405060708090a0b0c0d0e0f10");
  87. }
  88. TEST(B3PropagationTest, DoNotExtractWithInvalidHex)
  89. {
  90. TextMapCarrierTest carrier;
  91. carrier.headers_ = {{"b3", "0000000zzz0000000000000000000000-0000000zzz000000-1"}};
  92. context::Context ctx1 = context::Context{};
  93. context::Context ctx2 = format.Extract(carrier, ctx1);
  94. auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
  95. EXPECT_FALSE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
  96. }
  97. TEST(B3PropagationTest, SetRemoteSpan)
  98. {
  99. TextMapCarrierTest carrier;
  100. carrier.headers_ = {
  101. {"b3", "80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90"}};
  102. context::Context ctx1 = context::Context{};
  103. context::Context ctx2 = format.Extract(carrier, ctx1);
  104. auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
  105. EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
  106. auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
  107. EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7");
  108. EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
  109. EXPECT_EQ(span->GetContext().IsSampled(), true);
  110. EXPECT_EQ(span->GetContext().IsRemote(), true);
  111. }
  112. TEST(B3PropagationTest, SetRemoteSpan_TraceIdShort)
  113. {
  114. TextMapCarrierTest carrier;
  115. carrier.headers_ = {{"b3", "80f198ee56343ba8-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90"}};
  116. context::Context ctx1 = context::Context{};
  117. context::Context ctx2 = format.Extract(carrier, ctx1);
  118. auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
  119. EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
  120. auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
  121. EXPECT_EQ(Hex(span->GetContext().trace_id()), "000000000000000080f198ee56343ba8");
  122. EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
  123. EXPECT_EQ(span->GetContext().IsSampled(), true);
  124. EXPECT_EQ(span->GetContext().IsRemote(), true);
  125. }
  126. TEST(B3PropagationTest, SetRemoteSpan_SingleHeaderNoFlags)
  127. {
  128. TextMapCarrierTest carrier;
  129. carrier.headers_ = {{"b3", "80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1"}};
  130. context::Context ctx1 = context::Context{};
  131. context::Context ctx2 = format.Extract(carrier, ctx1);
  132. auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
  133. EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
  134. auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
  135. EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7");
  136. EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
  137. EXPECT_EQ(span->GetContext().IsSampled(), false);
  138. EXPECT_EQ(span->GetContext().IsRemote(), true);
  139. }
  140. TEST(B3PropagationTest, SetRemoteSpanMultiHeader)
  141. {
  142. TextMapCarrierTest carrier;
  143. carrier.headers_ = {{"X-B3-TraceId", "80f198ee56343ba864fe8b2a57d3eff7"},
  144. {"X-B3-SpanId", "e457b5a2e4d86bd1"},
  145. {"X-B3-Sampled", "1"}};
  146. context::Context ctx1 = context::Context{};
  147. context::Context ctx2 = format.Extract(carrier, ctx1);
  148. auto ctx2_span = ctx2.GetValue(trace::kSpanKey);
  149. EXPECT_TRUE(nostd::holds_alternative<nostd::shared_ptr<trace::Span>>(ctx2_span));
  150. auto span = nostd::get<nostd::shared_ptr<trace::Span>>(ctx2_span);
  151. EXPECT_EQ(Hex(span->GetContext().trace_id()), "80f198ee56343ba864fe8b2a57d3eff7");
  152. EXPECT_EQ(Hex(span->GetContext().span_id()), "e457b5a2e4d86bd1");
  153. EXPECT_EQ(span->GetContext().IsSampled(), true);
  154. EXPECT_EQ(span->GetContext().IsRemote(), true);
  155. }
  156. TEST(B3PropagationTest, GetCurrentSpan)
  157. {
  158. TextMapCarrierTest carrier;
  159. constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
  160. constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
  161. trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
  162. trace::TraceFlags{true}, false};
  163. nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
  164. // Set `sp` as the currently active span, which must be used by `Inject`.
  165. trace::Scope scoped_span{sp};
  166. format.Inject(carrier, context::RuntimeContext::GetCurrent());
  167. EXPECT_EQ(carrier.headers_["b3"], "0102030405060708090a0b0c0d0e0f10-0102030405060708-1");
  168. }
  169. TEST(B3PropagationTest, GetCurrentSpanMultiHeader)
  170. {
  171. TextMapCarrierTest carrier;
  172. constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8};
  173. constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
  174. trace::SpanContext span_context{trace::TraceId{buf_trace}, trace::SpanId{buf_span},
  175. trace::TraceFlags{true}, false};
  176. nostd::shared_ptr<trace::Span> sp{new trace::DefaultSpan{span_context}};
  177. // Set `sp` as the currently active span, which must be used by `Inject`.
  178. trace::Scope scoped_span{sp};
  179. formatMultiHeader.Inject(carrier, context::RuntimeContext::GetCurrent());
  180. EXPECT_EQ(carrier.headers_["X-B3-TraceId"], "0102030405060708090a0b0c0d0e0f10");
  181. EXPECT_EQ(carrier.headers_["X-B3-SpanId"], "0102030405060708");
  182. EXPECT_EQ(carrier.headers_["X-B3-Sampled"], "1");
  183. }