1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
4 #include "opentelemetry/context/propagation/global_propagator.h"
5 #include "opentelemetry/context/runtime_context.h"
6 #include "opentelemetry/trace/context.h"
7 #include "opentelemetry/trace/propagation/http_trace_context.h"
8 #include "opentelemetry/trace/scope.h"
12 #include <unordered_map>
14 #include <gtest/gtest.h>
16 using namespace opentelemetry
;
18 class TextMapCarrierTest
: public context::propagation::TextMapCarrier
21 virtual nostd::string_view
Get(nostd::string_view key
) const noexcept override
23 auto it
= headers_
.find(std::string(key
));
24 if (it
!= headers_
.end())
26 return nostd::string_view(it
->second
);
30 virtual void Set(nostd::string_view key
, nostd::string_view value
) noexcept override
32 headers_
[std::string(key
)] = std::string(value
);
35 std::map
<std::string
, std::string
> headers_
;
38 using MapHttpTraceContext
= trace::propagation::HttpTraceContext
;
40 static MapHttpTraceContext format
= MapHttpTraceContext();
42 TEST(TextMapPropagatorTest
, TraceFlagsBufferGeneration
)
44 EXPECT_EQ(MapHttpTraceContext::TraceFlagsFromHex("00"), trace::TraceFlags());
47 TEST(TextMapPropagatorTest
, NoSendEmptyTraceState
)
49 // If the trace state is empty, do not set the header.
50 TextMapCarrierTest carrier
;
51 carrier
.headers_
= {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"}};
52 context::Context ctx1
= context::Context
{
54 nostd::shared_ptr
<trace::Span
>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
55 context::Context ctx2
= format
.Extract(carrier
, ctx1
);
56 TextMapCarrierTest carrier2
;
57 format
.Inject(carrier2
, ctx2
);
58 EXPECT_TRUE(carrier2
.headers_
.count("traceparent") > 0);
59 EXPECT_FALSE(carrier2
.headers_
.count("tracestate") > 0);
62 TEST(TextMapPropagatorTest
, PropogateTraceState
)
64 TextMapCarrierTest carrier
;
65 carrier
.headers_
= {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"},
66 {"tracestate", "congo=t61rcWkgMzE"}};
67 context::Context ctx1
= context::Context
{
69 nostd::shared_ptr
<trace::Span
>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
70 context::Context ctx2
= format
.Extract(carrier
, ctx1
);
72 TextMapCarrierTest carrier2
;
73 format
.Inject(carrier2
, ctx2
);
75 EXPECT_TRUE(carrier2
.headers_
.count("traceparent") > 0);
76 EXPECT_TRUE(carrier2
.headers_
.count("tracestate") > 0);
77 EXPECT_EQ(carrier2
.headers_
["tracestate"], "congo=t61rcWkgMzE");
80 TEST(TextMapPropagatorTest
, PropagateInvalidContext
)
82 // Do not propagate invalid trace context.
83 TextMapCarrierTest carrier
;
86 nostd::shared_ptr
<trace::Span
>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
87 format
.Inject(carrier
, ctx
);
88 EXPECT_TRUE(carrier
.headers_
.count("traceparent") == 0);
89 EXPECT_TRUE(carrier
.headers_
.count("tracestate") == 0);
92 TEST(TextMapPropagatorTest
, SetRemoteSpan
)
94 TextMapCarrierTest carrier
;
95 carrier
.headers_
= {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"}};
96 context::Context ctx1
= context::Context
{};
97 context::Context ctx2
= format
.Extract(carrier
, ctx1
);
99 auto ctx2_span
= ctx2
.GetValue(trace::kSpanKey
);
100 EXPECT_TRUE(nostd::holds_alternative
<nostd::shared_ptr
<trace::Span
>>(ctx2_span
));
102 auto span
= nostd::get
<nostd::shared_ptr
<trace::Span
>>(ctx2_span
);
104 EXPECT_EQ(Hex(span
->GetContext().trace_id()), "4bf92f3577b34da6a3ce929d0e0e4736");
105 EXPECT_EQ(Hex(span
->GetContext().span_id()), "0102030405060708");
106 EXPECT_EQ(span
->GetContext().IsSampled(), true);
107 EXPECT_EQ(span
->GetContext().IsRemote(), true);
110 TEST(TextMapPropagatorTest
, GetCurrentSpan
)
112 TextMapCarrierTest carrier
;
113 constexpr uint8_t buf_span
[] = {1, 2, 3, 4, 5, 6, 7, 8};
114 constexpr uint8_t buf_trace
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
116 auto trace_state
= trace::TraceState::FromHeader("congo=t61rcWkgMzE");
117 trace::SpanContext span_context
{trace::TraceId
{buf_trace
}, trace::SpanId
{buf_span
},
118 trace::TraceFlags
{true}, false, trace_state
};
119 nostd::shared_ptr
<trace::Span
> sp
{new trace::DefaultSpan
{span_context
}};
121 // Set `sp` as the currently active span, which must be used by `Inject`.
122 trace::Scope scoped_span
{sp
};
124 format
.Inject(carrier
, context::RuntimeContext::GetCurrent());
125 EXPECT_EQ(carrier
.headers_
["traceparent"],
126 "00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01");
127 EXPECT_EQ(carrier
.headers_
["tracestate"], "congo=t61rcWkgMzE");
130 TEST(TextMapPropagatorTest
, InvalidIdentitiesAreNotExtracted
)
132 TextMapCarrierTest carrier
;
133 std::vector
<std::string
> traces
= {
134 "ff-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01",
135 "00-0af7651916cd43dd8448eb211c80319c1-b9c7c989f97918e1-01",
136 "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e11-01",
137 "0-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01",
138 "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-0",
139 "00-0af7651916cd43dd8448eb211c8031-b9c7c989f97918e1-01",
140 "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97-01",
142 "00--b9c7c989f97918e1-01",
143 "00-0af7651916cd43dd8448eb211c80319c1--01",
148 for (auto &trace
: traces
)
150 carrier
.headers_
= {{"traceparent", trace
}};
151 context::Context ctx1
= context::Context
{};
152 context::Context ctx2
= format
.Extract(carrier
, ctx1
);
154 auto span
= trace::GetSpan(ctx2
)->GetContext();
155 EXPECT_FALSE(span
.IsValid());
159 TEST(GlobalTextMapPropagator
, NoOpPropagator
)
162 auto propagator
= context::propagation::GlobalTextMapPropagator::GetGlobalPropagator();
163 TextMapCarrierTest carrier
;
165 carrier
.headers_
= {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"},
166 {"tracestate", "congo=t61rcWkgMzE"}};
167 context::Context ctx1
= context::Context
{
169 nostd::shared_ptr
<trace::Span
>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
170 context::Context ctx2
= propagator
->Extract(carrier
, ctx1
);
172 TextMapCarrierTest carrier2
;
173 propagator
->Inject(carrier2
, ctx2
);
175 EXPECT_TRUE(carrier2
.headers_
.count("tracestate") == 0);
176 EXPECT_TRUE(carrier2
.headers_
.count("traceparent") == 0);
179 TEST(GlobalPropagator
, SetAndGet
)
182 auto trace_state_value
= "congo=t61rcWkgMzE";
183 context::propagation::GlobalTextMapPropagator::SetGlobalPropagator(
184 nostd::shared_ptr
<context::propagation::TextMapPropagator
>(new MapHttpTraceContext()));
186 auto propagator
= context::propagation::GlobalTextMapPropagator::GetGlobalPropagator();
188 TextMapCarrierTest carrier
;
189 carrier
.headers_
= {{"traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-0102030405060708-01"},
190 {"tracestate", trace_state_value
}};
191 context::Context ctx1
= context::Context
{
193 nostd::shared_ptr
<trace::Span
>(new trace::DefaultSpan(trace::SpanContext::GetInvalid()))};
194 context::Context ctx2
= propagator
->Extract(carrier
, ctx1
);
196 TextMapCarrierTest carrier2
;
197 propagator
->Inject(carrier2
, ctx2
);
199 EXPECT_TRUE(carrier
.headers_
.count("traceparent") > 0);
200 EXPECT_TRUE(carrier
.headers_
.count("tracestate") > 0);
201 EXPECT_EQ(carrier
.headers_
["tracestate"], trace_state_value
);
203 std::vector
<std::string
> fields
;
204 propagator
->Fields([&fields
](nostd::string_view field
) {
205 fields
.push_back(field
.data());
208 EXPECT_EQ(fields
.size(), 2);
209 EXPECT_EQ(fields
[0], trace::propagation::kTraceParent
);
210 EXPECT_EQ(fields
[1], trace::propagation::kTraceState
);