1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
4 #include "opentelemetry/sdk/trace/tracer.h"
5 #include "opentelemetry/exporters/memory/in_memory_span_exporter.h"
6 #include "opentelemetry/sdk/resource/resource.h"
7 #include "opentelemetry/sdk/trace/samplers/always_off.h"
8 #include "opentelemetry/sdk/trace/samplers/always_on.h"
9 #include "opentelemetry/sdk/trace/samplers/parent.h"
10 #include "opentelemetry/sdk/trace/simple_processor.h"
11 #include "opentelemetry/sdk/trace/span_data.h"
12 #include "opentelemetry/trace/context.h"
14 #include <gtest/gtest.h>
16 using namespace opentelemetry::sdk::trace
;
17 using namespace opentelemetry::sdk::resource
;
18 using opentelemetry::common::SteadyTimestamp
;
19 using opentelemetry::common::SystemTimestamp
;
20 namespace nostd
= opentelemetry::nostd
;
21 namespace common
= opentelemetry::common
;
22 using opentelemetry::common::KeyValueIterableView
;
23 using opentelemetry::exporter::memory::InMemorySpanData
;
24 using opentelemetry::exporter::memory::InMemorySpanExporter
;
25 using opentelemetry::trace::SpanContext
;
28 * A mock sampler with ShouldSample returning:
29 * Decision::RECORD_AND_SAMPLE if trace_id is valid
30 * Decision::DROP otherwise.
32 class MockSampler final
: public Sampler
35 SamplingResult
ShouldSample(
36 const SpanContext
& /*parent_context*/,
37 trace_api::TraceId trace_id
,
38 nostd::string_view
/*name*/,
39 trace_api::SpanKind
/*span_kind*/,
40 const opentelemetry::common::KeyValueIterable
& /*attributes*/,
41 const opentelemetry::trace::SpanContextKeyValueIterable
& /*links*/) noexcept override
43 // Sample only if valid trace_id ( This is to test Sampler get's valid trace id)
44 if (trace_id
.IsValid())
46 // Return two pairs of attributes. These attributes should be added to the
48 return {Decision::RECORD_AND_SAMPLE
,
49 nostd::unique_ptr
<const std::map
<std::string
, opentelemetry::common::AttributeValue
>>(
50 new const std::map
<std::string
, opentelemetry::common::AttributeValue
>(
51 {{"sampling_attr1", 123}, {"sampling_attr2", "string"}}))};
55 // we should never reach here
57 return {Decision::DROP
};
61 nostd::string_view
GetDescription() const noexcept override
{ return "MockSampler"; }
65 * A Mock Custom Id Generator
67 class MockIdGenerator
: public IdGenerator
69 opentelemetry::trace::SpanId
GenerateSpanId() noexcept override
71 return opentelemetry::trace::SpanId(buf_span
);
74 opentelemetry::trace::TraceId
GenerateTraceId() noexcept override
76 return opentelemetry::trace::TraceId(buf_trace
);
78 uint8_t buf_span
[8] = {1, 2, 3, 4, 5, 6, 7, 8};
79 uint8_t buf_trace
[16] = {1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1};
84 std::shared_ptr
<opentelemetry::trace::Tracer
> initTracer(std::unique_ptr
<SpanExporter
> &&exporter
)
86 auto processor
= std::unique_ptr
<SpanProcessor
>(new SimpleSpanProcessor(std::move(exporter
)));
87 std::vector
<std::unique_ptr
<SpanProcessor
>> processors
;
88 processors
.push_back(std::move(processor
));
89 auto context
= std::make_shared
<TracerContext
>(std::move(processors
));
90 return std::shared_ptr
<opentelemetry::trace::Tracer
>(new Tracer(context
));
93 std::shared_ptr
<opentelemetry::trace::Tracer
> initTracer(
94 std::unique_ptr
<SpanExporter
> &&exporter
,
95 // For testing, just shove a pointer over, we'll take it over.
97 IdGenerator
*id_generator
= new RandomIdGenerator
)
99 auto processor
= std::unique_ptr
<SpanProcessor
>(new SimpleSpanProcessor(std::move(exporter
)));
100 std::vector
<std::unique_ptr
<SpanProcessor
>> processors
;
101 processors
.push_back(std::move(processor
));
102 auto resource
= Resource::Create({});
103 auto context
= std::make_shared
<TracerContext
>(std::move(processors
), resource
,
104 std::unique_ptr
<Sampler
>(sampler
),
105 std::unique_ptr
<IdGenerator
>(id_generator
));
106 return std::shared_ptr
<opentelemetry::trace::Tracer
>(new Tracer(context
));
111 TEST(Tracer
, ToInMemorySpanExporter
)
113 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
114 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
115 auto tracer
= initTracer(std::move(exporter
));
117 auto span_first
= tracer
->StartSpan("span 1");
118 auto scope_first
= tracer
->WithActiveSpan(span_first
);
119 auto span_second
= tracer
->StartSpan("span 2");
121 ASSERT_EQ(0, span_data
->GetSpans().size());
125 auto span2
= span_data
->GetSpans();
126 ASSERT_EQ(1, span2
.size());
127 ASSERT_EQ("span 2", span2
.at(0)->GetName());
128 EXPECT_TRUE(span2
.at(0)->GetTraceId().IsValid());
129 EXPECT_TRUE(span2
.at(0)->GetSpanId().IsValid());
130 EXPECT_TRUE(span2
.at(0)->GetParentSpanId().IsValid());
134 auto span1
= span_data
->GetSpans();
135 ASSERT_EQ(1, span1
.size());
136 ASSERT_EQ("span 1", span1
.at(0)->GetName());
137 EXPECT_TRUE(span1
.at(0)->GetTraceId().IsValid());
138 EXPECT_TRUE(span1
.at(0)->GetSpanId().IsValid());
139 EXPECT_FALSE(span1
.at(0)->GetParentSpanId().IsValid());
141 // Verify trace and parent span id propagation
142 EXPECT_EQ(span1
.at(0)->GetTraceId(), span2
.at(0)->GetTraceId());
143 EXPECT_EQ(span2
.at(0)->GetParentSpanId(), span1
.at(0)->GetSpanId());
146 TEST(Tracer
, StartSpanSampleOn
)
148 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
149 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
150 auto tracer_on
= initTracer(std::move(exporter
));
152 tracer_on
->StartSpan("span 1")->End();
154 auto spans
= span_data
->GetSpans();
155 ASSERT_EQ(1, spans
.size());
157 auto &cur_span_data
= spans
.at(0);
158 ASSERT_LT(std::chrono::nanoseconds(0), cur_span_data
->GetStartTime().time_since_epoch());
159 ASSERT_LT(std::chrono::nanoseconds(0), cur_span_data
->GetDuration());
162 TEST(Tracer
, StartSpanSampleOff
)
164 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
165 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
166 auto tracer_off
= initTracer(std::move(exporter
), new AlwaysOffSampler());
168 // This span will not be recorded.
169 auto span
= tracer_off
->StartSpan("span 2");
171 // Always generate a valid span-context (span-id)
172 auto context
= span
->GetContext();
173 EXPECT_TRUE(context
.IsValid());
174 EXPECT_FALSE(context
.IsSampled());
177 // The span doesn't write any span data because the sampling decision is alway
179 ASSERT_EQ(0, span_data
->GetSpans().size());
182 TEST(Tracer
, StartSpanCustomIdGenerator
)
184 IdGenerator
*id_generator
= new MockIdGenerator();
185 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
186 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
187 auto tracer
= initTracer(std::move(exporter
), new AlwaysOnSampler(), id_generator
);
189 tracer
->StartSpan("span 1")->End();
190 auto spans
= span_data
->GetSpans();
191 auto &cur_span_data
= spans
.at(0);
193 EXPECT_EQ(cur_span_data
->GetTraceId(), id_generator
->GenerateTraceId());
194 EXPECT_EQ(cur_span_data
->GetSpanId(), id_generator
->GenerateSpanId());
197 TEST(Tracer
, StartSpanWithOptionsTime
)
199 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
200 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
201 auto tracer
= initTracer(std::move(exporter
));
203 opentelemetry::trace::StartSpanOptions start
;
204 start
.start_system_time
= SystemTimestamp(std::chrono::nanoseconds(300));
205 start
.start_steady_time
= SteadyTimestamp(std::chrono::nanoseconds(10));
207 opentelemetry::trace::EndSpanOptions end
;
208 end
.end_steady_time
= SteadyTimestamp(std::chrono::nanoseconds(40));
210 tracer
->StartSpan("span 1", start
)->End(end
);
212 auto spans
= span_data
->GetSpans();
213 ASSERT_EQ(1, spans
.size());
215 auto &cur_span_data
= spans
.at(0);
216 ASSERT_EQ(std::chrono::nanoseconds(300), cur_span_data
->GetStartTime().time_since_epoch());
217 ASSERT_EQ(std::chrono::nanoseconds(30), cur_span_data
->GetDuration());
220 TEST(Tracer
, StartSpanWithAttributes
)
222 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
223 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
224 auto tracer
= initTracer(std::move(exporter
));
226 // Start a span with all supported scalar attribute types.
228 ->StartSpan("span 1", {{"attr1", "string"},
231 {"attr3", (unsigned int)314159},
232 {"attr4", (int32_t)-20},
233 {"attr5", (uint32_t)20},
234 {"attr6", (int64_t)-20},
235 {"attr7", (uint64_t)20},
237 {"attr9", "string"}})
240 // Start a span with all supported array attribute types.
241 int listInt
[] = {1, 2, 3};
242 unsigned int listUInt
[] = {1, 2, 3};
243 int32_t listInt32
[] = {1, -2, 3};
244 uint32_t listUInt32
[] = {1, 2, 3};
245 int64_t listInt64
[] = {1, -2, 3};
246 uint64_t listUInt64
[] = {1, 2, 3};
247 double listDouble
[] = {1.1, 2.1, 3.1};
248 bool listBool
[] = {true, false};
249 nostd::string_view listStringView
[] = {"a", "b"};
250 std::map
<std::string
, common::AttributeValue
> m
;
251 m
["attr1"] = nostd::span
<int>(listInt
);
252 m
["attr2"] = nostd::span
<unsigned int>(listUInt
);
253 m
["attr3"] = nostd::span
<int32_t>(listInt32
);
254 m
["attr4"] = nostd::span
<uint32_t>(listUInt32
);
255 m
["attr5"] = nostd::span
<int64_t>(listInt64
);
256 m
["attr6"] = nostd::span
<uint64_t>(listUInt64
);
257 m
["attr7"] = nostd::span
<double>(listDouble
);
258 m
["attr8"] = nostd::span
<bool>(listBool
);
259 m
["attr9"] = nostd::span
<nostd::string_view
>(listStringView
);
261 tracer
->StartSpan("span 2", m
)->End();
263 auto spans
= span_data
->GetSpans();
264 ASSERT_EQ(2, spans
.size());
266 auto &cur_span_data
= spans
.at(0);
267 ASSERT_EQ(9, cur_span_data
->GetAttributes().size());
268 ASSERT_EQ(314159, nostd::get
<int32_t>(cur_span_data
->GetAttributes().at("attr1")));
269 ASSERT_EQ(false, nostd::get
<bool>(cur_span_data
->GetAttributes().at("attr2")));
270 ASSERT_EQ(314159, nostd::get
<uint32_t>(cur_span_data
->GetAttributes().at("attr3")));
271 ASSERT_EQ(-20, nostd::get
<int32_t>(cur_span_data
->GetAttributes().at("attr4")));
272 ASSERT_EQ(20, nostd::get
<uint32_t>(cur_span_data
->GetAttributes().at("attr5")));
273 ASSERT_EQ(-20, nostd::get
<int64_t>(cur_span_data
->GetAttributes().at("attr6")));
274 ASSERT_EQ(20, nostd::get
<uint64_t>(cur_span_data
->GetAttributes().at("attr7")));
275 ASSERT_EQ(3.1, nostd::get
<double>(cur_span_data
->GetAttributes().at("attr8")));
276 ASSERT_EQ("string", nostd::get
<std::string
>(cur_span_data
->GetAttributes().at("attr9")));
278 auto &cur_span_data2
= spans
.at(1);
279 ASSERT_EQ(9, cur_span_data2
->GetAttributes().size());
280 ASSERT_EQ(std::vector
<int32_t>({1, 2, 3}),
281 nostd::get
<std::vector
<int32_t>>(cur_span_data2
->GetAttributes().at("attr1")));
282 ASSERT_EQ(std::vector
<uint32_t>({1, 2, 3}),
283 nostd::get
<std::vector
<uint32_t>>(cur_span_data2
->GetAttributes().at("attr2")));
284 ASSERT_EQ(std::vector
<int32_t>({1, -2, 3}),
285 nostd::get
<std::vector
<int32_t>>(cur_span_data2
->GetAttributes().at("attr3")));
286 ASSERT_EQ(std::vector
<uint32_t>({1, 2, 3}),
287 nostd::get
<std::vector
<uint32_t>>(cur_span_data2
->GetAttributes().at("attr4")));
288 ASSERT_EQ(std::vector
<int64_t>({1, -2, 3}),
289 nostd::get
<std::vector
<int64_t>>(cur_span_data2
->GetAttributes().at("attr5")));
290 ASSERT_EQ(std::vector
<uint64_t>({1, 2, 3}),
291 nostd::get
<std::vector
<uint64_t>>(cur_span_data2
->GetAttributes().at("attr6")));
292 ASSERT_EQ(std::vector
<double>({1.1, 2.1, 3.1}),
293 nostd::get
<std::vector
<double>>(cur_span_data2
->GetAttributes().at("attr7")));
294 ASSERT_EQ(std::vector
<bool>({true, false}),
295 nostd::get
<std::vector
<bool>>(cur_span_data2
->GetAttributes().at("attr8")));
296 ASSERT_EQ(std::vector
<std::string
>({"a", "b"}),
297 nostd::get
<std::vector
<std::string
>>(cur_span_data2
->GetAttributes().at("attr9")));
300 TEST(Tracer
, StartSpanWithAttributesCopy
)
302 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
303 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
304 auto tracer
= initTracer(std::move(exporter
));
307 std::unique_ptr
<std::vector
<int64_t>> numbers(new std::vector
<int64_t>);
308 numbers
->push_back(1);
309 numbers
->push_back(2);
310 numbers
->push_back(3);
312 std::unique_ptr
<std::vector
<nostd::string_view
>> strings(new std::vector
<nostd::string_view
>);
316 strings
->push_back(s1
);
317 strings
->push_back(s2
);
318 strings
->push_back(s3
);
320 ->StartSpan("span 1",
321 {{"attr1", *numbers
}, {"attr2", nostd::span
<nostd::string_view
>(*strings
)}})
325 auto spans
= span_data
->GetSpans();
326 ASSERT_EQ(1, spans
.size());
328 auto &cur_span_data
= spans
.at(0);
329 ASSERT_EQ(2, cur_span_data
->GetAttributes().size());
331 auto numbers
= nostd::get
<std::vector
<int64_t>>(cur_span_data
->GetAttributes().at("attr1"));
332 ASSERT_EQ(3, numbers
.size());
333 ASSERT_EQ(1, numbers
[0]);
334 ASSERT_EQ(2, numbers
[1]);
335 ASSERT_EQ(3, numbers
[2]);
337 auto strings
= nostd::get
<std::vector
<std::string
>>(cur_span_data
->GetAttributes().at("attr2"));
338 ASSERT_EQ(3, strings
.size());
339 ASSERT_EQ("a", strings
[0]);
340 ASSERT_EQ("b", strings
[1]);
341 ASSERT_EQ("c", strings
[2]);
344 TEST(Tracer
, GetSampler
)
346 auto resource
= Resource::Create({});
347 // Create a Tracer with a default AlwaysOnSampler
348 auto tracer_on
= initTracer(nullptr);
350 #ifdef OPENTELEMETRY_RTTI_ENABLED
351 auto &t1
= std::dynamic_pointer_cast
<Tracer
>(tracer_on
)->GetSampler();
353 auto &t1
= std::static_pointer_cast
<Tracer
>(tracer_on
)->GetSampler();
355 ASSERT_EQ("AlwaysOnSampler", t1
.GetDescription());
357 // Create a Tracer with a AlwaysOffSampler
358 auto tracer_off
= initTracer(nullptr, new AlwaysOffSampler());
360 #ifdef OPENTELEMETRY_RTTI_ENABLED
361 auto &t2
= std::dynamic_pointer_cast
<Tracer
>(tracer_off
)->GetSampler();
363 auto &t2
= std::static_pointer_cast
<Tracer
>(tracer_off
)->GetSampler();
365 ASSERT_EQ("AlwaysOffSampler", t2
.GetDescription());
368 TEST(Tracer
, SpanSetAttribute
)
370 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
371 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
372 auto tracer
= initTracer(std::move(exporter
));
374 auto span
= tracer
->StartSpan("span 1");
376 span
->SetAttribute("abc", 3.1);
380 auto spans
= span_data
->GetSpans();
381 ASSERT_EQ(1, spans
.size());
382 auto &cur_span_data
= spans
.at(0);
383 ASSERT_EQ(3.1, nostd::get
<double>(cur_span_data
->GetAttributes().at("abc")));
386 TEST(Tracer
, TestAfterEnd
)
388 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
389 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
390 auto tracer
= initTracer(std::move(exporter
));
391 auto span
= tracer
->StartSpan("span 1");
392 span
->SetAttribute("abc", 3.1);
397 span
->SetAttribute("testing null recordable", 3.1);
398 span
->AddEvent("event 1");
399 span
->AddEvent("event 2", std::chrono::system_clock::now());
400 span
->AddEvent("event 3", std::chrono::system_clock::now(), {{"attr1", 1}});
401 std::string new_name
{"new name"};
402 span
->UpdateName(new_name
);
403 span
->SetAttribute("attr1", 3.1);
404 std::string description
{"description"};
405 span
->SetStatus(opentelemetry::trace::StatusCode::kError
, description
);
408 auto spans
= span_data
->GetSpans();
409 ASSERT_EQ(1, spans
.size());
410 auto &cur_span_data
= spans
.at(0);
411 ASSERT_EQ(3.1, nostd::get
<double>(cur_span_data
->GetAttributes().at("abc")));
414 TEST(Tracer
, SpanSetEvents
)
416 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
417 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
418 auto tracer
= initTracer(std::move(exporter
));
420 auto span
= tracer
->StartSpan("span 1");
421 span
->AddEvent("event 1");
422 span
->AddEvent("event 2", std::chrono::system_clock::now());
423 span
->AddEvent("event 3", std::chrono::system_clock::now(), {{"attr1", 1}});
426 auto spans
= span_data
->GetSpans();
427 ASSERT_EQ(1, spans
.size());
429 auto &span_data_events
= spans
.at(0)->GetEvents();
430 ASSERT_EQ(3, span_data_events
.size());
431 ASSERT_EQ("event 1", span_data_events
[0].GetName());
432 ASSERT_EQ("event 2", span_data_events
[1].GetName());
433 ASSERT_EQ("event 3", span_data_events
[2].GetName());
434 ASSERT_EQ(0, span_data_events
[0].GetAttributes().size());
435 ASSERT_EQ(0, span_data_events
[1].GetAttributes().size());
436 ASSERT_EQ(1, span_data_events
[2].GetAttributes().size());
439 TEST(Tracer
, SpanSetLinks
)
441 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
442 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
443 auto tracer
= initTracer(std::move(exporter
));
447 // Single span link passed through Initialization list
448 tracer
->StartSpan("efg", {{"attr1", 1}}, {{SpanContext(false, false), {{"attr2", 2}}}})->End();
449 auto spans
= span_data
->GetSpans();
450 ASSERT_EQ(1, spans
.size());
452 auto &span_data_links
= spans
.at(0)->GetLinks();
453 ASSERT_EQ(1, span_data_links
.size());
454 auto link
= span_data_links
.at(0);
455 ASSERT_EQ(nostd::get
<int>(link
.GetAttributes().at("attr2")), 2);
459 // Multiple span links passed through Initialization list
461 ->StartSpan("efg", {{"attr1", 1}},
462 {{SpanContext(false, false), {{"attr2", 2}}},
463 {SpanContext(false, false), {{"attr3", 3}}}})
465 auto spans
= span_data
->GetSpans();
466 ASSERT_EQ(1, spans
.size());
468 auto &span_data_links
= spans
.at(0)->GetLinks();
469 ASSERT_EQ(2, span_data_links
.size());
470 auto link1
= span_data_links
.at(0);
471 ASSERT_EQ(nostd::get
<int>(link1
.GetAttributes().at("attr2")), 2);
472 auto link2
= span_data_links
.at(1);
473 ASSERT_EQ(nostd::get
<int>(link2
.GetAttributes().at("attr3")), 3);
478 // Multiple links, each with multiple attributes passed through Initialization list
480 ->StartSpan("efg", {{"attr1", 1}},
481 {{SpanContext(false, false), {{"attr2", 2}, {"attr3", 3}}},
482 {SpanContext(false, false), {{"attr4", 4}}}})
484 auto spans
= span_data
->GetSpans();
485 ASSERT_EQ(1, spans
.size());
487 auto &span_data_links
= spans
.at(0)->GetLinks();
488 ASSERT_EQ(2, span_data_links
.size());
489 auto link1
= span_data_links
.at(0);
490 ASSERT_EQ(nostd::get
<int>(link1
.GetAttributes().at("attr2")), 2);
491 ASSERT_EQ(nostd::get
<int>(link1
.GetAttributes().at("attr3")), 3);
492 auto link2
= span_data_links
.at(1);
493 ASSERT_EQ(nostd::get
<int>(link2
.GetAttributes().at("attr4")), 4);
497 std::map
<std::string
, std::string
> attrs1
= {{"attr1", "1"}, {"attr2", "2"}};
498 std::map
<std::string
, std::string
> attrs2
= {{"attr3", "3"}, {"attr4", "4"}};
500 std::vector
<std::pair
<SpanContext
, std::map
<std::string
, std::string
>>> links
= {
501 {SpanContext(false, false), attrs1
}, {SpanContext(false, false), attrs2
}};
502 tracer
->StartSpan("efg", attrs1
, links
)->End();
503 auto spans
= span_data
->GetSpans();
505 auto &span_data_links
= spans
.at(0)->GetLinks();
506 ASSERT_EQ(2, span_data_links
.size());
507 auto link1
= span_data_links
.at(0);
508 ASSERT_EQ(nostd::get
<std::string
>(link1
.GetAttributes().at("attr1")), "1");
509 ASSERT_EQ(nostd::get
<std::string
>(link1
.GetAttributes().at("attr2")), "2");
510 auto link2
= span_data_links
.at(1);
511 ASSERT_EQ(nostd::get
<std::string
>(link2
.GetAttributes().at("attr3")), "3");
512 ASSERT_EQ(nostd::get
<std::string
>(link2
.GetAttributes().at("attr4")), "4");
516 TEST(Tracer
, TestAlwaysOnSampler
)
518 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
519 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
520 auto tracer_on
= initTracer(std::move(exporter
));
522 // Testing AlwaysOn sampler.
523 // Create two spans for each tracer. Check the exported result.
524 auto span_on_1
= tracer_on
->StartSpan("span 1");
525 auto span_on_2
= tracer_on
->StartSpan("span 2");
529 auto spans
= span_data
->GetSpans();
530 ASSERT_EQ(2, spans
.size());
531 ASSERT_EQ("span 2", spans
.at(0)->GetName()); // span 2 ends first.
532 ASSERT_EQ("span 1", spans
.at(1)->GetName());
535 TEST(Tracer
, TestAlwaysOffSampler
)
537 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
538 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
539 auto tracer_off
= initTracer(std::move(exporter
), new AlwaysOffSampler());
540 auto span_off_1
= tracer_off
->StartSpan("span 1");
541 auto span_off_2
= tracer_off
->StartSpan("span 2");
543 span_off_1
->SetAttribute("attr1", 3.1); // Not recorded.
548 // The tracer export nothing with an AlwaysOff sampler
549 ASSERT_EQ(0, span_data
->GetSpans().size());
552 TEST(Tracer
, TestParentBasedSampler
)
554 // Current ShouldSample always pass an empty ParentContext,
555 // so this sampler will work as an AlwaysOnSampler.
556 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
557 std::shared_ptr
<InMemorySpanData
> span_data_parent_on
= exporter
->GetData();
558 auto tracer_parent_on
=
559 initTracer(std::move(exporter
), new ParentBasedSampler(std::make_shared
<AlwaysOnSampler
>()));
561 auto span_parent_on_1
= tracer_parent_on
->StartSpan("span 1");
562 auto span_parent_on_2
= tracer_parent_on
->StartSpan("span 2");
564 span_parent_on_1
->SetAttribute("attr1", 3.1);
566 span_parent_on_2
->End();
567 span_parent_on_1
->End();
569 auto spans
= span_data_parent_on
->GetSpans();
570 ASSERT_EQ(2, spans
.size());
571 ASSERT_EQ("span 2", spans
.at(0)->GetName());
572 ASSERT_EQ("span 1", spans
.at(1)->GetName());
574 // Current ShouldSample always pass an empty ParentContext,
575 // so this sampler will work as an AlwaysOnSampler.
576 std::unique_ptr
<InMemorySpanExporter
> exporter2(new InMemorySpanExporter());
577 std::shared_ptr
<InMemorySpanData
> span_data_parent_off
= exporter2
->GetData();
578 auto tracer_parent_off
=
579 initTracer(std::move(exporter2
),
580 // Add this to avoid different results for old and new version of clang-format
581 new ParentBasedSampler(std::make_shared
<AlwaysOffSampler
>()));
583 auto span_parent_off_1
= tracer_parent_off
->StartSpan("span 1");
584 auto span_parent_off_2
= tracer_parent_off
->StartSpan("span 2");
586 span_parent_off_1
->SetAttribute("attr1", 3.1);
588 span_parent_off_1
->End();
589 span_parent_off_2
->End();
590 ASSERT_EQ(0, span_data_parent_off
->GetSpans().size());
593 TEST(Tracer
, WithActiveSpan
)
595 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
596 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
597 auto tracer
= initTracer(std::move(exporter
));
598 auto spans
= span_data
.get()->GetSpans();
600 ASSERT_EQ(0, spans
.size());
603 auto span_first
= tracer
->StartSpan("span 1");
604 auto scope_first
= tracer
->WithActiveSpan(span_first
);
607 auto span_second
= tracer
->StartSpan("span 2");
608 auto scope_second
= tracer
->WithActiveSpan(span_second
);
610 spans
= span_data
->GetSpans();
611 ASSERT_EQ(0, spans
.size());
616 spans
= span_data
->GetSpans();
617 ASSERT_EQ(1, spans
.size());
618 EXPECT_EQ("span 2", spans
.at(0)->GetName());
623 spans
= span_data
->GetSpans();
624 ASSERT_EQ(1, spans
.size());
625 EXPECT_EQ("span 1", spans
.at(0)->GetName());
628 TEST(Tracer
, ExpectParent
)
630 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
631 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
632 auto tracer
= initTracer(std::move(exporter
));
633 auto spans
= span_data
.get()->GetSpans();
635 ASSERT_EQ(0, spans
.size());
637 auto span_first
= tracer
->StartSpan("span 1");
639 trace_api::StartSpanOptions options
;
640 options
.parent
= span_first
->GetContext();
641 auto span_second
= tracer
->StartSpan("span 2", options
);
643 options
.parent
= span_second
->GetContext();
644 auto span_third
= tracer
->StartSpan("span 3", options
);
650 spans
= span_data
->GetSpans();
651 ASSERT_EQ(3, spans
.size());
652 auto spandata_first
= std::move(spans
.at(2));
653 auto spandata_second
= std::move(spans
.at(1));
654 auto spandata_third
= std::move(spans
.at(0));
655 EXPECT_EQ("span 1", spandata_first
->GetName());
656 EXPECT_EQ("span 2", spandata_second
->GetName());
657 EXPECT_EQ("span 3", spandata_third
->GetName());
659 EXPECT_EQ(spandata_first
->GetSpanId(), spandata_second
->GetParentSpanId());
660 EXPECT_EQ(spandata_second
->GetSpanId(), spandata_third
->GetParentSpanId());
663 TEST(Tracer
, ExpectParentAsContext
)
665 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
666 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
667 auto tracer
= initTracer(std::move(exporter
));
668 auto spans
= span_data
.get()->GetSpans();
670 ASSERT_EQ(0, spans
.size());
672 auto span_first
= tracer
->StartSpan("span 1");
674 opentelemetry::context::Context c1
;
675 auto c2
= trace_api::SetSpan(c1
, span_first
);
676 trace_api::StartSpanOptions options
;
678 auto span_second
= tracer
->StartSpan("span 2", options
);
680 auto c3
= trace_api::SetSpan(c2
, span_second
);
682 auto span_third
= tracer
->StartSpan("span 3", options
);
688 spans
= span_data
->GetSpans();
689 ASSERT_EQ(3, spans
.size());
690 auto spandata_first
= std::move(spans
.at(2));
691 auto spandata_second
= std::move(spans
.at(1));
692 auto spandata_third
= std::move(spans
.at(0));
693 EXPECT_EQ("span 1", spandata_first
->GetName());
694 EXPECT_EQ("span 2", spandata_second
->GetName());
695 EXPECT_EQ("span 3", spandata_third
->GetName());
697 EXPECT_EQ(spandata_first
->GetSpanId(), spandata_second
->GetParentSpanId());
698 EXPECT_EQ(spandata_second
->GetSpanId(), spandata_third
->GetParentSpanId());
701 TEST(Tracer
, ValidTraceIdToSampler
)
703 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
704 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
705 auto tracer
= initTracer(std::move(exporter
), new MockSampler());
707 auto span
= tracer
->StartSpan("span 1");
708 // sampler was fed with valid trace_id, so span shouldn't be NoOp Span.
709 EXPECT_TRUE(span
->IsRecording());
710 EXPECT_TRUE(span
->GetContext().IsValid());
713 TEST(Tracer
, SpanCleanupWithScope
)
715 std::unique_ptr
<InMemorySpanExporter
> exporter(new InMemorySpanExporter());
716 std::shared_ptr
<InMemorySpanData
> span_data
= exporter
->GetData();
717 auto tracer
= initTracer(std::move(exporter
));
719 auto span0
= tracer
->StartSpan("Span0");
720 auto span1
= tracer
->StartSpan("span1");
722 trace_api::Scope
scope(span1
);
723 auto span2
= tracer
->StartSpan("span2");
725 trace_api::Scope
scope(span2
);
726 auto span3
= tracer
->StartSpan("span3");
730 EXPECT_EQ(4, span_data
->GetSpans().size());