]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentelemetry-cpp/exporters/zipkin/test/zipkin_recordable_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / exporters / zipkin / test / zipkin_recordable_test.cc
1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3
4 #include "opentelemetry/sdk/trace/recordable.h"
5 #include "opentelemetry/sdk/trace/simple_processor.h"
6 #include "opentelemetry/sdk/trace/span_data.h"
7 #include "opentelemetry/sdk/trace/tracer_provider.h"
8 #include "opentelemetry/trace/provider.h"
9
10 #include "opentelemetry/sdk/trace/exporter.h"
11
12 #include "opentelemetry/common/timestamp.h"
13 #include "opentelemetry/exporters/zipkin/recordable.h"
14
15 #include <gtest/gtest.h>
16
17 namespace trace = opentelemetry::trace;
18 namespace nostd = opentelemetry::nostd;
19 namespace sdktrace = opentelemetry::sdk::trace;
20 namespace common = opentelemetry::common;
21 namespace zipkin = opentelemetry::exporter::zipkin;
22 using json = nlohmann::json;
23
24 // Testing Shutdown functionality of OStreamSpanExporter, should expect no data to be sent to Stream
25 TEST(ZipkinSpanRecordable, SetIdentity)
26 {
27 json j_span = {{"id", "0000000000000002"},
28 {"parentId", "0000000000000003"},
29 {"traceId", "00000000000000000000000000000001"}};
30 zipkin::Recordable rec;
31 const trace::TraceId trace_id(std::array<const uint8_t, trace::TraceId::kSize>(
32 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}));
33
34 const trace::SpanId span_id(
35 std::array<const uint8_t, trace::SpanId::kSize>({0, 0, 0, 0, 0, 0, 0, 2}));
36
37 const trace::SpanId parent_span_id(
38 std::array<const uint8_t, trace::SpanId::kSize>({0, 0, 0, 0, 0, 0, 0, 3}));
39
40 const trace::SpanContext span_context{trace_id, span_id,
41 trace::TraceFlags{trace::TraceFlags::kIsSampled}, true};
42
43 rec.SetIdentity(span_context, parent_span_id);
44 EXPECT_EQ(rec.span(), j_span);
45 }
46
47 // according to https://zipkin.io/zipkin-api/#/ in case root span is created
48 // the parentId filed should be absent.
49 TEST(ZipkinSpanRecordable, SetIdentityEmptyParent)
50 {
51 json j_span = {{"id", "0000000000000002"}, {"traceId", "00000000000000000000000000000001"}};
52 zipkin::Recordable rec;
53 const trace::TraceId trace_id(std::array<const uint8_t, trace::TraceId::kSize>(
54 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}));
55
56 const trace::SpanId span_id(
57 std::array<const uint8_t, trace::SpanId::kSize>({0, 0, 0, 0, 0, 0, 0, 2}));
58
59 const trace::SpanId parent_span_id(
60 std::array<const uint8_t, trace::SpanId::kSize>({0, 0, 0, 0, 0, 0, 0, 0}));
61
62 const trace::SpanContext span_context{trace_id, span_id,
63 trace::TraceFlags{trace::TraceFlags::kIsSampled}, true};
64
65 rec.SetIdentity(span_context, parent_span_id);
66 EXPECT_EQ(rec.span(), j_span);
67 }
68
69 TEST(ZipkinSpanRecordable, SetName)
70 {
71 nostd::string_view name = "Test Span";
72 json j_span = {{"name", name}};
73 zipkin::Recordable rec;
74 rec.SetName(name);
75 EXPECT_EQ(rec.span(), j_span);
76 }
77
78 TEST(ZipkinSpanRecordable, SetStartTime)
79 {
80 zipkin::Recordable rec;
81 std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now();
82 common::SystemTimestamp start_timestamp(start_time);
83
84 uint64_t unix_start =
85 std::chrono::duration_cast<std::chrono::microseconds>(start_time.time_since_epoch()).count();
86 json j_span = {{"timestamp", unix_start}};
87 rec.SetStartTime(start_timestamp);
88 EXPECT_EQ(rec.span(), j_span);
89 }
90
91 TEST(ZipkinSpanRecordable, SetDuration)
92 {
93 std::chrono::nanoseconds durationNS(1000000000); // in ns
94 std::chrono::microseconds durationMS =
95 std::chrono::duration_cast<std::chrono::microseconds>(durationNS); // in ms
96 json j_span = {{"duration", durationMS.count()}, {"timestamp", 0}};
97 zipkin::Recordable rec;
98 // Start time is 0
99 common::SystemTimestamp start_timestamp;
100
101 rec.SetStartTime(start_timestamp);
102 rec.SetDuration(durationNS);
103 EXPECT_EQ(rec.span(), j_span);
104 }
105
106 TEST(ZipkinSpanRecordable, SetInstrumentationLibrary)
107 {
108 using InstrumentationLibrary = opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary;
109
110 const char *library_name = "otel-cpp";
111 const char *library_version = "0.5.0";
112 json j_span = {
113 {"tags", {{"otel.library.name", library_name}, {"otel.library.version", library_version}}}};
114 zipkin::Recordable rec;
115
116 rec.SetInstrumentationLibrary(*InstrumentationLibrary::Create(library_name, library_version));
117
118 EXPECT_EQ(rec.span(), j_span);
119 }
120
121 TEST(ZipkinSpanRecordable, SetStatus)
122 {
123 std::string description = "Error description";
124 std::vector<trace::StatusCode> status_codes = {trace::StatusCode::kError, trace::StatusCode::kOk};
125 for (auto &status_code : status_codes)
126 {
127 zipkin::Recordable rec;
128 trace::StatusCode code(status_code);
129 json j_span;
130 if (status_code == trace::StatusCode::kError)
131 j_span = {{"tags", {{"otel.status_code", status_code}, {"error", description}}}};
132 else
133 j_span = {{"tags", {{"otel.status_code", status_code}}}};
134
135 rec.SetStatus(code, description);
136 EXPECT_EQ(rec.span(), j_span);
137 }
138 }
139
140 TEST(ZipkinSpanRecordable, SetSpanKind)
141 {
142 json j_json_client = {{"kind", "CLIENT"}};
143 zipkin::Recordable rec;
144 rec.SetSpanKind(trace::SpanKind::kClient);
145 EXPECT_EQ(rec.span(), j_json_client);
146 }
147
148 TEST(ZipkinSpanRecordable, AddEventDefault)
149 {
150 zipkin::Recordable rec;
151 nostd::string_view name = "Test Event";
152
153 std::chrono::system_clock::time_point event_time = std::chrono::system_clock::now();
154 common::SystemTimestamp event_timestamp(event_time);
155
156 rec.sdktrace::Recordable::AddEvent(name, event_timestamp);
157
158 uint64_t unix_event_time =
159 std::chrono::duration_cast<std::chrono::microseconds>(event_time.time_since_epoch()).count();
160
161 json j_span = {
162 {"annotations",
163 {{{"value", json({{name, json::object()}}).dump()}, {"timestamp", unix_event_time}}}}};
164 EXPECT_EQ(rec.span(), j_span);
165 }
166
167 TEST(ZipkinSpanRecordable, AddEventWithAttributes)
168 {
169 zipkin::Recordable rec;
170
171 std::chrono::system_clock::time_point event_time = std::chrono::system_clock::now();
172 common::SystemTimestamp event_timestamp(event_time);
173 uint64_t unix_event_time =
174 std::chrono::duration_cast<std::chrono::microseconds>(event_time.time_since_epoch()).count();
175
176 const int kNumAttributes = 3;
177 std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3"};
178 int values[kNumAttributes] = {4, 7, 23};
179 std::map<std::string, int> attributes = {
180 {keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}};
181
182 rec.AddEvent("Test Event", event_timestamp,
183 common::KeyValueIterableView<std::map<std::string, int>>(attributes));
184
185 nlohmann::json j_span = {
186 {"annotations",
187 {{{"value", json({{"Test Event", {{"attr1", 4}, {"attr2", 7}, {"attr3", 23}}}}).dump()},
188 {"timestamp", unix_event_time}}}}};
189 EXPECT_EQ(rec.span(), j_span);
190 }
191
192 // Test non-int single types. Int single types are tested using templates (see IntAttributeTest)
193 TEST(ZipkinSpanRecordable, SetSingleAtrribute)
194 {
195 zipkin::Recordable rec;
196 nostd::string_view bool_key = "bool_attr";
197 common::AttributeValue bool_val(true);
198 rec.SetAttribute(bool_key, bool_val);
199
200 nostd::string_view double_key = "double_attr";
201 common::AttributeValue double_val(3.3);
202 rec.SetAttribute(double_key, double_val);
203
204 nostd::string_view str_key = "str_attr";
205 common::AttributeValue str_val(nostd::string_view("Test"));
206 rec.SetAttribute(str_key, str_val);
207 nlohmann::json j_span = {
208 {"tags", {{"bool_attr", true}, {"double_attr", 3.3}, {"str_attr", "Test"}}}};
209
210 EXPECT_EQ(rec.span(), j_span);
211 }
212
213 // Test non-int array types. Int array types are tested using templates (see IntAttributeTest)
214 TEST(ZipkinSpanRecordable, SetArrayAtrribute)
215 {
216 zipkin::Recordable rec;
217 nlohmann::json j_span = {{"tags",
218 {{"bool_arr_attr", {true, false, true}},
219 {"double_arr_attr", {22.3, 33.4, 44.5}},
220 {"str_arr_attr", {"Hello", "World", "Test"}}}}};
221 const int kArraySize = 3;
222
223 bool bool_arr[kArraySize] = {true, false, true};
224 nostd::span<const bool> bool_span(bool_arr);
225 rec.SetAttribute("bool_arr_attr", bool_span);
226
227 double double_arr[kArraySize] = {22.3, 33.4, 44.5};
228 nostd::span<const double> double_span(double_arr);
229 rec.SetAttribute("double_arr_attr", double_span);
230
231 nostd::string_view str_arr[kArraySize] = {"Hello", "World", "Test"};
232 nostd::span<const nostd::string_view> str_span(str_arr);
233 rec.SetAttribute("str_arr_attr", str_span);
234
235 EXPECT_EQ(rec.span(), j_span);
236 }
237
238 TEST(ZipkinSpanRecordable, SetResource)
239 {
240 zipkin::Recordable rec;
241 std::string service_name = "test";
242 auto resource = opentelemetry::sdk::resource::Resource::Create({{"service.name", service_name}});
243 rec.SetResource(resource);
244 EXPECT_EQ(rec.GetServiceName(), service_name);
245 }
246
247 /**
248 * AttributeValue can contain different int types, such as int, int64_t,
249 * unsigned int, and uint64_t. To avoid writing test cases for each, we can
250 * use a template approach to test all int types.
251 */
252 template <typename T>
253 struct ZipkinIntAttributeTest : public testing::Test
254 {
255 using IntParamType = T;
256 };
257
258 using IntTypes = testing::Types<int, int64_t, unsigned int, uint64_t>;
259 TYPED_TEST_SUITE(ZipkinIntAttributeTest, IntTypes);
260
261 TYPED_TEST(ZipkinIntAttributeTest, SetIntSingleAttribute)
262 {
263 using IntType = typename TestFixture::IntParamType;
264 IntType i = 2;
265 common::AttributeValue int_val(i);
266
267 zipkin::Recordable rec;
268 rec.SetAttribute("int_attr", int_val);
269 nlohmann::json j_span = {{"tags", {{"int_attr", 2}}}};
270 EXPECT_EQ(rec.span(), j_span);
271 }
272
273 TYPED_TEST(ZipkinIntAttributeTest, SetIntArrayAttribute)
274 {
275 using IntType = typename TestFixture::IntParamType;
276
277 const int kArraySize = 3;
278 IntType int_arr[kArraySize] = {4, 5, 6};
279 nostd::span<const IntType> int_span(int_arr);
280
281 zipkin::Recordable rec;
282 rec.SetAttribute("int_arr_attr", int_span);
283 nlohmann::json j_span = {{"tags", {{"int_arr_attr", {4, 5, 6}}}}};
284 EXPECT_EQ(rec.span(), j_span);
285 }