]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/opentelemetry-cpp/ext/test/zpages/tracez_data_aggregator_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / ext / test / zpages / tracez_data_aggregator_test.cc
CommitLineData
1e59de90
TL
1// Copyright The OpenTelemetry Authors
2// SPDX-License-Identifier: Apache-2.0
3
4#include "opentelemetry/ext/zpages/tracez_data_aggregator.h"
5
6#include <gtest/gtest.h>
7
8#include "opentelemetry/ext/zpages/tracez_processor.h"
9#include "opentelemetry/sdk/resource/resource.h"
10#include "opentelemetry/sdk/trace/recordable.h"
11#include "opentelemetry/sdk/trace/tracer.h"
12
13using namespace opentelemetry::sdk::trace;
14using namespace opentelemetry::ext::zpages;
15namespace nostd = opentelemetry::nostd;
16namespace common = opentelemetry::common;
17using opentelemetry::common::SteadyTimestamp;
18using opentelemetry::trace::Span;
19
20const std::string span_name1 = "span 1";
21const std::string span_name2 = "span 2";
22const std::string span_name3 = "span 3";
23
24/**
25 * TODO: Due to the absence of way to simulate the passing of time in the
26 * testing framework, synthetic delays had to be added in the tests to get the
27 * object in question to perform correctly. Later on if something like this is
28 * added the tests should be modified accordingly so that there is no external
29 * dependency.
30 * Additionally later on it would be better check for the span id(when set)
31 * rather than span name.
32 */
33
34/** Test fixture for setting up the data aggregator and tracer for each test **/
35class TracezDataAggregatorTest : public ::testing::Test
36{
37protected:
38 void SetUp() override
39 {
40 std::shared_ptr<TracezSharedData> shared_data(new TracezSharedData());
41 auto resource = opentelemetry::sdk::resource::Resource::Create({});
42 std::unique_ptr<SpanProcessor> processor(new TracezSpanProcessor(shared_data));
43 std::vector<std::unique_ptr<SpanProcessor>> processors;
44 processors.push_back(std::move(processor));
45
46 auto context = std::make_shared<TracerContext>(std::move(processors), resource);
47 tracer = std::shared_ptr<opentelemetry::trace::Tracer>(new Tracer(context));
48 tracez_data_aggregator = std::unique_ptr<TracezDataAggregator>(
49 new TracezDataAggregator(shared_data, milliseconds(10)));
50 }
51
52 std::unique_ptr<TracezDataAggregator> tracez_data_aggregator;
53 std::shared_ptr<opentelemetry::trace::Tracer> tracer;
54};
55
56/**
57 * Helper function to check if the counts of running, error and latency spans
58 * match what is expected
59 */
60void VerifySpanCountsInTracezData(
61 const std::string &span_name,
62 const TracezData &aggregated_data,
63 size_t running_span_count,
64 size_t error_span_count,
65 std::array<unsigned int, kLatencyBoundaries.size()> completed_span_count_per_latency_bucket)
66{
67 // Asserts are needed to check the size of the container because they may need
68 // to be checked and if size checks fail it must be stopped
69 EXPECT_EQ(aggregated_data.running_span_count, running_span_count)
70 << " Count of running spans incorrect for " << span_name << "\n";
71
72 EXPECT_EQ(aggregated_data.sample_running_spans.size(),
73 std::min<size_t>(running_span_count, kMaxNumberOfSampleSpans))
74 << " Size of sample running spans incorrect for " << span_name << "\n";
75
76 EXPECT_EQ(aggregated_data.error_span_count, error_span_count)
77 << " Count of error spans incorrect for " << span_name << "\n";
78
79 EXPECT_EQ(aggregated_data.sample_error_spans.size(),
80 std::min<size_t>(error_span_count, kMaxNumberOfSampleSpans))
81 << " Count of running spans incorrect for " << span_name << "\n";
82
83 for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size(); boundary++)
84 {
85 EXPECT_EQ(aggregated_data.completed_span_count_per_latency_bucket[boundary],
86 completed_span_count_per_latency_bucket[boundary])
87 << " Count of completed spans in latency boundary " << boundary << " incorrect for "
88 << span_name << "\n";
89 EXPECT_EQ(aggregated_data.sample_latency_spans[boundary].size(),
90 std::min<size_t>(completed_span_count_per_latency_bucket[boundary],
91 kMaxNumberOfSampleSpans))
92 << " Count of sample completed spans in latency boundary " << boundary << " incorrect for "
93 << span_name << "\n";
94 }
95}
96
97/**************************** No Span Test ************************************/
98
99/** Test to check if data aggregator works as expected when there are no spans
100 * **/
101TEST_F(TracezDataAggregatorTest, NoSpans)
102{
103 auto data = tracez_data_aggregator->GetAggregatedTracezData();
104 ASSERT_EQ(data.size(), 0);
105}
106
107/*********************** Single span tests ************************************/
108
109/** Test to check if data aggregator works as expected when there are
110 * is exactly a single running span **/
111TEST_F(TracezDataAggregatorTest, SingleRunningSpan)
112{
113 // Start the span get the data
114 auto span_first = tracer->StartSpan(span_name1);
115 std::this_thread::sleep_for(milliseconds(500));
116 auto data = tracez_data_aggregator->GetAggregatedTracezData();
117
118 // Check to see if span name exists
119 ASSERT_EQ(data.size(), 1);
120 ASSERT_TRUE(data.find(span_name1) != data.end());
121 auto &aggregated_data = data.at(span_name1);
122
123 // Verify span counts then content of spans
124 VerifySpanCountsInTracezData(span_name1, aggregated_data, 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0});
125
126 ASSERT_EQ(aggregated_data.sample_running_spans.size(), 1);
127 ASSERT_EQ(aggregated_data.sample_running_spans.front().GetName().data(), span_name1);
128 span_first->End();
129}
130
131/** Test to check if data aggregator works as expected when there is exactly one
132 * completed span **/
133TEST_F(TracezDataAggregatorTest, SingleCompletedSpan)
134{
135 // Start and end the span at a specified times
136 opentelemetry::trace::StartSpanOptions start;
137 start.start_steady_time = SteadyTimestamp(nanoseconds(10));
138 opentelemetry::trace::EndSpanOptions end;
139 end.end_steady_time = SteadyTimestamp(nanoseconds(40));
140 tracer->StartSpan(span_name1, start)->End(end);
141
142 // Get the data and make sure span name exists in the data
143 std::this_thread::sleep_for(milliseconds(500));
144 auto data = tracez_data_aggregator->GetAggregatedTracezData();
145 ASSERT_EQ(data.size(), 1);
146 ASSERT_TRUE(data.find(span_name1) != data.end());
147
148 auto &aggregated_data = data.at(span_name1);
149 // Make sure counts of spans are in order
150 VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0});
151
152 // Check if the span is correctly updated in the first boundary
153 ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro].size(), 1);
154 ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro]
155 .front()
156 .GetDuration()
157 .count(),
158 30);
159}
160
161/** Test to check if data aggregator works as expected when there is exactly
162 * one error span **/
163TEST_F(TracezDataAggregatorTest, SingleErrorSpan)
164{
165 // Start and end a single error span
166 auto span = tracer->StartSpan(span_name1);
167 span->SetStatus(opentelemetry::trace::StatusCode::kError, "span cancelled");
168 span->End();
169 std::this_thread::sleep_for(milliseconds(500));
170 auto data = tracez_data_aggregator->GetAggregatedTracezData();
171
172 // Check to see if span name can be found in aggregation
173 ASSERT_EQ(data.size(), 1);
174 ASSERT_TRUE(data.find(span_name1) != data.end());
175
176 auto &aggregated_data = data.at(span_name1);
177 // Make sure counts of spans are in order
178 VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 1, {0, 0, 0, 0, 0, 0, 0, 0, 0});
179
180 // Check the value of the error span introduced
181 ASSERT_EQ(aggregated_data.sample_error_spans.size(), 1);
182 ASSERT_EQ(aggregated_data.sample_error_spans.front().GetName().data(), span_name1);
183}
184
185/************************* Multiple span tests ********************************/
186
187/** Test to check if multiple running spans behaves as expected**/
188TEST_F(TracezDataAggregatorTest, MultipleRunningSpans)
189{
190 // A container that maps a span name to the number of spans to start with that
191 // span name
192 std::unordered_map<std::string, int> running_span_name_to_count({
193 {span_name1, 1},
194 {span_name2, 2},
195 {span_name3, 3},
196 });
197
198 // Start and store spans based on the above map
199 std::vector<nostd::shared_ptr<Span>> running_span_container;
200 for (auto span_name : running_span_name_to_count)
201 {
202 for (int count = 0; count < span_name.second; count++)
203 running_span_container.push_back(tracer->StartSpan(span_name.first));
204 }
205
206 // give time for aggregation and then get data
207 std::this_thread::sleep_for(milliseconds(500));
208 auto data = tracez_data_aggregator->GetAggregatedTracezData();
209 ASSERT_EQ(data.size(), running_span_name_to_count.size());
210
211 // Check to see if the running span counts were updated correctly
212 for (auto &span_name : running_span_name_to_count)
213 {
214 ASSERT_TRUE(data.find(span_name.first) != data.end());
215
216 // Make sure counts of spans are in order
217 VerifySpanCountsInTracezData(span_name.first, data.at(span_name.first), span_name.second, 0,
218 {0, 0, 0, 0, 0, 0, 0, 0, 0});
219
220 ASSERT_EQ(data.at(span_name.first).sample_running_spans.size(), span_name.second);
221 for (auto &span_sample : data.at(span_name.first).sample_running_spans)
222 {
223 ASSERT_EQ(span_sample.GetName().data(), span_name.first);
224 }
225 }
226
227 for (auto i = running_span_container.begin(); i != running_span_container.end(); i++)
228 (*i)->End();
229}
230
231/** Test to check if multiple completed spans updates the aggregated data
232 * correctly **/
233TEST_F(TracezDataAggregatorTest, MultipleCompletedSpan)
234{
235 // Start spans with span name and the corresponding durations in one of the 9
236 // latency buckets
237 const std::unordered_map<std::string, std::vector<std::vector<nanoseconds>>>
238 span_name_to_duration(
239 {{span_name1, {{nanoseconds(10), nanoseconds(4600)}, {}, {}, {}, {}, {}, {}, {}, {}}},
240 {span_name2,
241 {{},
242 {nanoseconds(38888), nanoseconds(98768)},
243 {nanoseconds(983251)},
244 {},
245 {},
246 {},
247 {},
248 {},
249 {}}},
250 {span_name3,
251 {{},
252 {},
253 {},
254 {nanoseconds(1234567), nanoseconds(1234567)},
255 {},
256 {},
257 {},
258 {},
259 {nanoseconds(9999999999999)}}}});
260 opentelemetry::trace::StartSpanOptions start;
261 opentelemetry::trace::EndSpanOptions end;
262 for (auto &span : span_name_to_duration)
263 {
264 for (auto &buckets : span.second)
265 {
266 for (auto &duration : buckets)
267 {
268 long long int end_time = duration.count() + 1;
269 start.start_steady_time = SteadyTimestamp(nanoseconds(1));
270 end.end_steady_time = SteadyTimestamp(nanoseconds(end_time));
271 tracer->StartSpan(span.first, start)->End(end);
272 }
273 }
274 }
275
276 // Give time for aggregation and get data
277 std::this_thread::sleep_for(milliseconds(500));
278 auto data = tracez_data_aggregator->GetAggregatedTracezData();
279
280 ASSERT_EQ(data.size(), span_name_to_duration.size());
281
282 for (auto &span : span_name_to_duration)
283 {
284 ASSERT_TRUE(data.find(span.first) != data.end());
285 auto &aggregated_data = data.at(span.first);
286
287 // Make sure counts of spans are in order
288 VerifySpanCountsInTracezData(
289 span.first, aggregated_data, 0, 0,
290 {(unsigned int)span.second[0].size(), (unsigned int)span.second[1].size(),
291 (unsigned int)span.second[2].size(), (unsigned int)span.second[3].size(),
292 (unsigned int)span.second[4].size(), (unsigned int)span.second[5].size(),
293 (unsigned int)span.second[6].size(), (unsigned int)span.second[7].size(),
294 (unsigned int)span.second[8].size()});
295
296 for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size(); boundary++)
297 {
298 ASSERT_EQ(aggregated_data.sample_latency_spans[boundary].size(),
299 span.second[boundary].size());
300 auto latency_sample = aggregated_data.sample_latency_spans[boundary].begin();
301 for (unsigned int idx = 0; idx < span.second[boundary].size(); idx++)
302 {
303 ASSERT_EQ(span.second[boundary][idx].count(), latency_sample->GetDuration().count());
304 latency_sample = std::next(latency_sample);
305 }
306 }
307 }
308}
309
310/**
311 * This test checks to see if the aggregated data is updated correctly
312 * when there are multiple error spans.
313 * It checks both the count of error spans and the error samples
314 */
315TEST_F(TracezDataAggregatorTest, MultipleErrorSpans)
316{
317 // Container to store the span names --> error messges for the span name
318 std::unordered_map<std::string, std::vector<std::string>> span_name_to_error(
319 {{span_name1, {"span 1 error"}},
320 {span_name2, {"span 2 error 1", "span 2 error 2"}},
321 {span_name3,
322 {"span 3 error 1", "span 3 error 2", "span 3 error 3", "span 3 error 4",
323 "span 3 error 5"}}});
324
325 // Start spans with the error messages based on the map
326 for (auto &span_error : span_name_to_error)
327 {
328 for (auto error_desc : span_error.second)
329 {
330 auto span = tracer->StartSpan(span_error.first);
331 span->SetStatus(opentelemetry::trace::StatusCode::kError, error_desc);
332 span->End();
333 }
334 }
335
336 // Give some time and then get data
337 std::this_thread::sleep_for(milliseconds(500));
338 auto data = tracez_data_aggregator->GetAggregatedTracezData();
339 ASSERT_EQ(data.size(), span_name_to_error.size());
340
341 // Check if error spans were updated correctly for the different span names
342 for (auto &span_error : span_name_to_error)
343 {
344 // First try to find the span name in aggregation, then check the count of
345 // the error spans and then check values
346 ASSERT_TRUE(data.find(span_error.first) != data.end());
347
348 auto &aggregated_data = data.at(span_error.first);
349
350 // Make sure counts of spans are in order
351 VerifySpanCountsInTracezData(span_error.first, aggregated_data, 0, span_error.second.size(),
352 {0, 0, 0, 0, 0, 0, 0, 0, 0});
353 ASSERT_EQ(aggregated_data.error_span_count, span_error.second.size());
354
355 auto error_sample = aggregated_data.sample_error_spans.begin();
356 for (unsigned int idx = 0; idx < span_error.second.size(); idx++)
357 {
358 ASSERT_EQ(span_error.second[idx], error_sample->GetDescription());
359 error_sample = std::next(error_sample);
360 }
361 }
362}
363
364/************************ Sample spans tests **********************************/
365
366/**
367 * This test checks to see that the maximum number of running samples(5) for a
368 * bucket is not exceeded. If there are more spans than this for a single bucket
369 * it removes the earliest span that was received
370 */
371TEST_F(TracezDataAggregatorTest, RunningSampleSpansOverCapacity)
372{
373 int running_span_count = 6;
374 // Start and store spans based on the above map
375 std::vector<nostd::shared_ptr<Span>> running_span_container;
376 for (int count = 0; count < running_span_count; count++)
377 running_span_container.push_back(tracer->StartSpan(span_name1));
378
379 std::this_thread::sleep_for(milliseconds(500));
380 // Fetch data and check if span name is spresent
381 auto data = tracez_data_aggregator->GetAggregatedTracezData();
382 ASSERT_EQ(data.size(), 1);
383 ASSERT_TRUE(data.find(span_name1) != data.end());
384
385 // Check if error spans are updated according to spans started
386 auto &aggregated_data = data.at(span_name1);
387 VerifySpanCountsInTracezData(span_name1, aggregated_data, 6, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0});
388
389 ASSERT_EQ(aggregated_data.sample_running_spans.size(), kMaxNumberOfSampleSpans);
390
391 for (auto i = running_span_container.begin(); i != running_span_container.end(); i++)
392 {
393 (*i)->End();
394 }
395}
396
397/**
398 * This test checks to see that the maximum number of error samples(5) for a
399 * bucket is not exceeded. If there are more spans than this for a single bucket
400 * it removes the earliest span that was received
401 */
402TEST_F(TracezDataAggregatorTest, ErrorSampleSpansOverCapacity)
403{
404 // Create error spans with the descriptions in the vector
405 std::vector<std::string> span_error_descriptions = {"error span 1", "error span 2",
406 "error span 3", "error span 4",
407 "error span 5", "error span 6"};
408 for (auto span_error_description : span_error_descriptions)
409 {
410 auto span = tracer->StartSpan(span_name1);
411 span->SetStatus(opentelemetry::trace::StatusCode::kError, span_error_description);
412 span->End();
413 }
414
415 std::this_thread::sleep_for(milliseconds(500));
416
417 // Fetch data and check if span name is spresent
418 auto data = tracez_data_aggregator->GetAggregatedTracezData();
419 ASSERT_EQ(data.size(), 1);
420 ASSERT_TRUE(data.find(span_name1) != data.end());
421
422 std::this_thread::sleep_for(milliseconds(500));
423
424 // Check if error spans are updated according to spans started
425 auto &aggregated_data = data.at(span_name1);
426 VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, span_error_descriptions.size(),
427 {0, 0, 0, 0, 0, 0, 0, 0, 0});
428
429 // Check if the latest 5 error spans exist out of the total 6 that were
430 // introduced
431 auto error_sample = aggregated_data.sample_error_spans.begin();
432 for (unsigned int idx = 1; idx < span_error_descriptions.size(); idx++)
433 {
434 ASSERT_EQ(error_sample->GetDescription(), span_error_descriptions[idx]);
435 error_sample = std::next(error_sample);
436 }
437}
438
439/**
440 * This test checks to see that the maximum number of latency samples(5) for a
441 * bucket is not exceeded. If there are more spans than this for a single bucket
442 * it removes the earliest span that was received
443 */
444TEST_F(TracezDataAggregatorTest, CompletedSampleSpansOverCapacity)
445{
446 opentelemetry::trace::StartSpanOptions start;
447 opentelemetry::trace::EndSpanOptions end;
448
449 // Start and end 6 spans with the same name that fall into the first latency
450 // bucket
451 std::vector<std::pair<nanoseconds, nanoseconds>> timestamps = {
452 make_pair(nanoseconds(10), nanoseconds(100)),
453 make_pair(nanoseconds(1), nanoseconds(10000)),
454 make_pair(nanoseconds(1000), nanoseconds(3000)),
455 make_pair(nanoseconds(12), nanoseconds(12)),
456 make_pair(nanoseconds(10), nanoseconds(5000)),
457 make_pair(nanoseconds(10), nanoseconds(60))};
458 for (auto timestamp : timestamps)
459 {
460 start.start_steady_time = SteadyTimestamp(timestamp.first);
461 end.end_steady_time = SteadyTimestamp(timestamp.second);
462 tracer->StartSpan(span_name1, start)->End(end);
463 }
464
465 // Give some time and get data
466 std::this_thread::sleep_for(milliseconds(500));
467 auto data = tracez_data_aggregator->GetAggregatedTracezData();
468
469 ASSERT_EQ(data.size(), 1);
470 ASSERT_TRUE(data.find(span_name1) != data.end());
471
472 std::this_thread::sleep_for(milliseconds(500));
473 auto &aggregated_data = data.at(span_name1);
474 VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0,
475 {(unsigned int)timestamps.size(), 0, 0, 0, 0, 0, 0, 0, 0});
476
477 // Check the count of completed spans in the buckets and the samples stored
478 auto latency_sample =
479 aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro].begin();
480
481 // idx starts from 1 and not 0 because there are 6 completed spans in the same
482 // bucket the and the first one is removed
483 for (unsigned int idx = 1; idx < timestamps.size(); idx++)
484 {
485 ASSERT_EQ(latency_sample->GetDuration().count(),
486 timestamps[idx].second.count() - timestamps[idx].first.count());
487 latency_sample = std::next(latency_sample);
488 }
489}
490
491/************************* Miscellaneous tests ********************************/
492
493/** Test to see if the span names are in alphabetical order **/
494TEST_F(TracezDataAggregatorTest, SpanNameInAlphabeticalOrder)
495{
496 std::vector<std::string> span_names = {span_name1, span_name2, span_name3};
497
498 auto span_first = tracer->StartSpan(span_name2);
499 tracer->StartSpan(span_name1)->End();
500 auto span_third = tracer->StartSpan(span_name3);
501 span_third->SetStatus(opentelemetry::trace::StatusCode::kError, "span cancelled");
502 span_third->End();
503 std::this_thread::sleep_for(milliseconds(500));
504 // Get data and check if span name exists in aggregation
505 auto data = tracez_data_aggregator->GetAggregatedTracezData();
506 ASSERT_EQ(data.size(), span_names.size());
507
508 int span_names_idx = 0;
509 for (auto &spans : data)
510 {
511 ASSERT_EQ(spans.first, span_names[span_names_idx]);
512 span_names_idx++;
513 }
514 span_first->End();
515}
516
517/** This test checks to see that there is no double counting of running spans
518 * when get aggregated data is called twice**/
519TEST_F(TracezDataAggregatorTest, AdditionToRunningSpans)
520{
521 // Start a span and check the data
522 auto span_first = tracer->StartSpan(span_name1);
523 std::this_thread::sleep_for(milliseconds(500));
524 auto data = tracez_data_aggregator->GetAggregatedTracezData();
525 ASSERT_EQ(data.size(), 1);
526 ASSERT_TRUE(data.find(span_name1) != data.end());
527 VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0});
528
529 // Start another span and check to see if there is no double counting of spans
530 auto span_second = tracer->StartSpan(span_name1);
531
532 // Give some time and get updated data
533 std::this_thread::sleep_for(milliseconds(500));
534 data = tracez_data_aggregator->GetAggregatedTracezData();
535 ASSERT_EQ(data.size(), 1);
536 ASSERT_TRUE(data.find(span_name1) != data.end());
537 auto &aggregated_data = data.at(span_name1);
538 VerifySpanCountsInTracezData(span_name1, aggregated_data, 2, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0});
539
540 ASSERT_EQ(aggregated_data.sample_running_spans.size(), 2);
541 for (auto &sample_span : aggregated_data.sample_running_spans)
542 {
543 ASSERT_EQ(sample_span.GetName().data(), span_name1);
544 }
545 span_first->End();
546 span_second->End();
547}
548
549/** This test checks to see that once a running span is completed it the
550 * aggregated data is updated correctly **/
551TEST_F(TracezDataAggregatorTest, RemovalOfRunningSpanWhenCompleted)
552{
553 opentelemetry::trace::StartSpanOptions start;
554 start.start_steady_time = SteadyTimestamp(nanoseconds(10));
555 opentelemetry::trace::EndSpanOptions end;
556 end.end_steady_time = SteadyTimestamp(nanoseconds(40));
557
558 // Start a span and make sure data is updated
559 auto span_first = tracer->StartSpan(span_name1, start);
560 std::this_thread::sleep_for(milliseconds(500));
561 auto data = tracez_data_aggregator->GetAggregatedTracezData();
562 ASSERT_EQ(data.size(), 1);
563 ASSERT_TRUE(data.find(span_name1) != data.end());
564 VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0});
565 ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName().data(), span_name1);
566 // End the span and make sure running span is removed and completed span is
567 // updated, there should be only one completed span
568 span_first->End(end);
569 std::this_thread::sleep_for(milliseconds(500));
570
571 // Make sure sample span still exists before next aggregation
572 ASSERT_TRUE(data.find(span_name1) != data.end());
573 ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName().data(), span_name1);
574
575 data = tracez_data_aggregator->GetAggregatedTracezData();
576
577 ASSERT_EQ(data.size(), 1);
578 ASSERT_TRUE(data.find(span_name1) != data.end());
579
580 // Check if completed span fields are correctly updated
581 auto &aggregated_data = data.at(span_name1);
582 VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0});
583 ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro]
584 .front()
585 .GetDuration()
586 .count(),
587 30);
588}
589
590TEST_F(TracezDataAggregatorTest, RunningSpanChangesNameBeforeCompletion)
591{
592 opentelemetry::trace::StartSpanOptions start;
593 start.start_steady_time = SteadyTimestamp(nanoseconds(10));
594 opentelemetry::trace::EndSpanOptions end;
595 end.end_steady_time = SteadyTimestamp(nanoseconds(40));
596
597 // Start a span and make sure data is updated
598 auto span_first = tracer->StartSpan(span_name1, start);
599 std::this_thread::sleep_for(milliseconds(500));
600 auto data = tracez_data_aggregator->GetAggregatedTracezData();
601 ASSERT_EQ(data.size(), 1);
602 ASSERT_TRUE(data.find(span_name1) != data.end());
603 VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0});
604 ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName().data(), span_name1);
605
606 // End the span and make sure running span is removed and completed span is
607 // updated, there should be only one completed span
608 span_first->UpdateName(span_name2);
609 span_first->End(end);
610
611 // Check if sample span is present before fetching updated data
612 std::this_thread::sleep_for(milliseconds(500));
613 ASSERT_TRUE(data.find(span_name1) != data.end());
614 ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName(), span_name1);
615
616 data = tracez_data_aggregator->GetAggregatedTracezData();
617
618 ASSERT_EQ(data.size(), 1);
619 ASSERT_TRUE(data.find(span_name2) != data.end());
620
621 // Check if completed span fields are correctly updated
622 auto &aggregated_data = data.at(span_name2);
623 VerifySpanCountsInTracezData(span_name2, aggregated_data, 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0});
624 ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro]
625 .front()
626 .GetDuration()
627 .count(),
628 30);
629}
630
631/** Test to check if the span latencies with duration at the edge of boundaries
632 * fall in the correct bucket **/
633TEST_F(TracezDataAggregatorTest, EdgeSpanLatenciesFallInCorrectBoundaries)
634{
635 opentelemetry::trace::StartSpanOptions start;
636 opentelemetry::trace::EndSpanOptions end;
637
638 // Start and end 6 spans with the same name that fall into the first latency
639 // bucket
640 std::vector<nanoseconds> durations = {
641 nanoseconds(0), nanoseconds(10000), nanoseconds(100000),
642 nanoseconds(1000000), nanoseconds(10000000), nanoseconds(100000000),
643 nanoseconds(1000000000), nanoseconds(10000000000), nanoseconds(100000000000)};
644 for (auto duration : durations)
645 {
646 start.start_steady_time = SteadyTimestamp(nanoseconds(1));
647 end.end_steady_time = SteadyTimestamp(nanoseconds(duration.count() + 1));
648 tracer->StartSpan(span_name1, start)->End(end);
649 }
650
651 std::this_thread::sleep_for(milliseconds(500));
652 auto data = tracez_data_aggregator->GetAggregatedTracezData();
653 ASSERT_EQ(data.size(), 1);
654 ASSERT_TRUE(data.find(span_name1) != data.end());
655
656 std::this_thread::sleep_for(milliseconds(500));
657 auto &aggregated_data = data.at(span_name1);
658 VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1});
659
660 // Check if the latency boundary is updated correctly
661 for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size(); boundary++)
662 {
663 ASSERT_EQ(aggregated_data.sample_latency_spans[boundary].front().GetDuration().count(),
664 durations[boundary].count());
665 }
666}
667
668/** This test makes sure that the data is consistent when there are multiple
669 * calls to the data aggegator with no change in data **/
670TEST_F(TracezDataAggregatorTest, NoChangeInBetweenCallsToAggregator)
671{
672 opentelemetry::trace::StartSpanOptions start;
673 start.start_steady_time = SteadyTimestamp(nanoseconds(1));
674
675 opentelemetry::trace::EndSpanOptions end;
676 end.end_steady_time = SteadyTimestamp(nanoseconds(1));
677
678 tracer->StartSpan(span_name1, start)->End(end);
679 auto running_span = tracer->StartSpan(span_name2);
680 auto span = tracer->StartSpan(span_name3);
681 span->SetStatus(opentelemetry::trace::StatusCode::kError, "span cancelled");
682 span->End();
683 std::this_thread::sleep_for(milliseconds(500));
684 auto data = tracez_data_aggregator->GetAggregatedTracezData();
685 std::this_thread::sleep_for(milliseconds(500));
686 // Get data and check if span name exists in aggregation
687 data = tracez_data_aggregator->GetAggregatedTracezData();
688 ASSERT_TRUE(data.find(span_name1) != data.end());
689 VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0});
690
691 ASSERT_TRUE(data.find(span_name2) != data.end());
692 VerifySpanCountsInTracezData(span_name2, data.at(span_name2), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0});
693
694 ASSERT_TRUE(data.find(span_name3) != data.end());
695 VerifySpanCountsInTracezData(span_name3, data.at(span_name3), 0, 1, {0, 0, 0, 0, 0, 0, 0, 0, 0});
696
697 running_span->End();
698}