]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentelemetry-cpp/exporters/etw/test/etw_tracer_test.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / exporters / etw / test / etw_tracer_test.cc
1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3
4 #ifdef _WIN32
5
6 # include <gtest/gtest.h>
7 # include <map>
8 # include <string>
9
10 # include "opentelemetry/exporters/etw/etw_tracer_exporter.h"
11 # include "opentelemetry/sdk/trace/simple_processor.h"
12
13 using namespace OPENTELEMETRY_NAMESPACE;
14
15 using namespace opentelemetry::exporter::etw;
16
17 const char *kGlobalProviderName = "OpenTelemetry-ETW-TLD";
18
19 std::string getTemporaryValue()
20 {
21 return std::string("Value from Temporary std::string");
22 }
23
24 /* clang-format off */
25 TEST(ETWTracer, TracerCheck)
26 {
27 // SDK customer specifies their unique ETW ProviderName. Every component or library
28 // is assumed to have its own instrumentation name. Traces are routed to dedicated
29 // provider. Standard hash function maps from ProviderName to ProviderGUID.
30 //
31 // Prominent naming examples from `logman query providers` :
32 //
33 // [Docker] {a3693192-9ed6-46d2-a981-f8226c8363bd}
34 // ...
35 // Intel-Autologger-iclsClient {B8D7E9A0-65D5-40BE-AFEA-83593FC0164E}
36 // Intel-Autologger-iclsProxy {301B773F-50F3-4C8E-83F0-53BA9590A13E}
37 // Intel-Autologger-PTTEKRecertification {F33E9E07-8792-47E8-B3FA-2C92AB32C5B3}
38 // ...
39 // NodeJS-ETW-provider {77754E9B-264B-4D8D-B981-E4135C1ECB0C}
40 // ...
41 // OpenSSH {C4B57D35-0636-4BC3-A262-370F249F9802}
42 // ...
43 // Windows Connect Now {C100BECE-D33A-4A4B-BF23-BBEF4663D017}
44 // Windows Defender Firewall API {28C9F48F-D244-45A8-842F-DC9FBC9B6E92}
45 // Windows Defender Firewall API - GP {0EFF663F-8B6E-4E6D-8182-087A8EAA29CB}
46 // Windows Defender Firewall Driver {D5E09122-D0B2-4235-ADC1-C89FAAAF1069}
47
48 std::string providerName = kGlobalProviderName; // supply unique instrumentation name here
49 exporter::etw::TracerProvider tp;
50
51 auto tracer = tp.GetTracer(providerName);
52
53 // Span attributes
54 Properties attribs =
55 {
56 {"attrib1", 1},
57 {"attrib2", 2}
58 };
59 {
60 auto topSpan = tracer->StartSpan("MySpanTop");
61 auto topScope = tracer->WithActiveSpan(topSpan);
62 {
63 auto outerSpan = tracer->StartSpan("MySpanL2", attribs);
64 auto outerScope = tracer->WithActiveSpan(outerSpan);
65
66 // Create nested span. Note how we share the attributes here.
67 // It is Okay to either reuse/share or have your own attributes.
68 {
69 auto innerSpan = tracer->StartSpan("MySpanL3", attribs);
70 auto innerScope = tracer->WithActiveSpan(innerSpan);
71
72 // Add span attribute
73 EXPECT_NO_THROW(outerSpan->SetAttribute("AttrName1", "AttrValue1"));
74
75 // Add first event
76 std::string eventName1 = "MyEvent1";
77 Properties event1 =
78 {
79 {"uint32Key", (uint32_t)1234},
80 {"uint64Key", (uint64_t)1234567890},
81 {"strKey", "someValue"}
82 };
83 EXPECT_NO_THROW(outerSpan->AddEvent(eventName1, event1));
84
85 // Add second event
86 std::string eventName2 = "MyEvent2";
87 Properties event2 =
88 {
89 {"uint32Key", (uint32_t)9876},
90 {"uint64Key", (uint64_t)987654321},
91 {"strKey", "anotherValue"}
92 };
93 EXPECT_NO_THROW(outerSpan->AddEvent(eventName2, event2));
94
95 std::string eventName3= "MyEvent3";
96 Properties event3 =
97 {
98 /* Extra metadata that allows event to flow to A.I. pipeline */
99 {"metadata", "ai_event"},
100 {"uint32Key", (uint32_t)9876},
101 {"uint64Key", (uint64_t)987654321},
102 // {"int32array", {{-1,0,1,2,3}} },
103 {"tempString", getTemporaryValue() }
104 };
105 EXPECT_NO_THROW(innerSpan->AddEvent(eventName3, event3));
106 EXPECT_NO_THROW(innerSpan->End());
107
108 }
109 EXPECT_NO_THROW(outerSpan->End());
110
111 }
112 EXPECT_NO_THROW(topSpan->End());
113 }
114
115 EXPECT_NO_THROW(tracer->CloseWithMicroseconds(0));
116 }
117
118 // Lowest decoration level -> smaller ETW event size.
119 // Expected output in C# listener on the other side:
120 // no ActivityID GUID, no SpanId, no TraceId.
121 /*
122 {
123 "Timestamp": "2021-03-19T21:04:38.411193-07:00",
124 "ProviderName": "OpenTelemetry-ETW-TLD",
125 "Id": 13,
126 "Message": null,
127 "ProcessId": 15120,
128 "Level": "Always",
129 "Keywords": "0x0000000000000000",
130 "EventName": "C.min/Stop",
131 "ActivityID": null,
132 "RelatedActivityID": null,
133 "Payload": {}
134 }
135 */
136 TEST(ETWTracer, TracerCheckMinDecoration)
137 {
138 std::string providerName = kGlobalProviderName;
139 exporter::etw::TracerProvider tp
140 ({
141 {"enableTraceId", false},
142 {"enableSpanId", false},
143 {"enableActivityId", false},
144 {"enableActivityTracking", true},
145 {"enableRelatedActivityId", false},
146 {"enableAutoParent", false}
147 });
148 auto tracer = tp.GetTracer(providerName);
149 {
150 auto aSpan = tracer->StartSpan("A.min");
151 auto aScope = tracer->WithActiveSpan(aSpan);
152 {
153 auto bSpan = tracer->StartSpan("B.min");
154 auto bScope = tracer->WithActiveSpan(bSpan);
155 {
156 auto cSpan = tracer->StartSpan("C.min");
157 auto cScope = tracer->WithActiveSpan(cSpan);
158 EXPECT_NO_THROW(cSpan->End());
159 }
160 EXPECT_NO_THROW(bSpan->End());
161 }
162 EXPECT_NO_THROW(aSpan->End());
163 }
164 tracer->CloseWithMicroseconds(0);
165 }
166
167 // Highest decoration level -> larger ETW event size
168 // Expected output in C# listener on the other side:
169 // ActivityID GUID (==SpanId), SpanId, TraceId.
170 /*
171 {
172 "Timestamp": "2021-03-19T21:04:38.4120274-07:00",
173 "ProviderName": "OpenTelemetry-ETW-TLD",
174 "Id": 21,
175 "Message": null,
176 "ProcessId": 15120,
177 "Level": "Always",
178 "Keywords": "0x0000000000000000",
179 "EventName": "C.max/Stop",
180 "ActivityID": "d55a2c25-8033-40ab-0000-000000000000",
181 "RelatedActivityID": null,
182 "Payload": {
183 "SpanId": "252c5ad53380ab40",
184 "TraceId": "4dea2a63c188894ea5ab979e5cd7ec36"
185 }
186 }
187 */
188 TEST(ETWTracer, TracerCheckMaxDecoration)
189 {
190 std::string providerName = kGlobalProviderName;
191 exporter::etw::TracerProvider tp
192 ({
193 {"enableTraceId", true},
194 {"enableSpanId", true},
195 {"enableActivityId", true},
196 {"enableRelatedActivityId", true},
197 {"enableAutoParent", true}
198 });
199 auto tracer = tp.GetTracer(providerName);
200 {
201 auto aSpan = tracer->StartSpan("A.max");
202 auto aScope = tracer->WithActiveSpan(aSpan);
203 {
204 auto bSpan = tracer->StartSpan("B.max");
205 auto bScope = tracer->WithActiveSpan(bSpan);
206 {
207 auto cSpan = tracer->StartSpan("C.max");
208 auto cScope = tracer->WithActiveSpan(cSpan);
209 EXPECT_NO_THROW(cSpan->End());
210 }
211 EXPECT_NO_THROW(bSpan->End());
212 }
213 EXPECT_NO_THROW(aSpan->End());
214 }
215 tracer->CloseWithMicroseconds(0);
216 }
217
218 TEST(ETWTracer, TracerCheckMsgPack)
219 {
220 std::string providerName = "OpenTelemetry-ETW-MsgPack";
221 exporter::etw::TracerProvider tp
222 ({
223 {"enableTraceId", true},
224 {"enableSpanId", true},
225 {"enableActivityId", true},
226 {"enableRelatedActivityId", true},
227 {"enableAutoParent", true}
228 });
229 auto tracer = tp.GetTracer(providerName);
230 {
231 auto aSpan = tracer->StartSpan("A.max");
232 auto aScope = tracer->WithActiveSpan(aSpan);
233 {
234 auto bSpan = tracer->StartSpan("B.max");
235 auto bScope = tracer->WithActiveSpan(bSpan);
236 {
237 auto cSpan = tracer->StartSpan("C.max");
238 auto cScope = tracer->WithActiveSpan(cSpan);
239 std::string eventName = "MyMsgPackEvent";
240 Properties event =
241 {
242 {"uint32Key", (uint32_t)1234},
243 {"uint64Key", (uint64_t)1234567890},
244 {"strKey", "someValue"}
245 };
246 cSpan->AddEvent(eventName, event);
247 EXPECT_NO_THROW(cSpan->End());
248 }
249 EXPECT_NO_THROW(bSpan->End());
250 }
251 EXPECT_NO_THROW(aSpan->End());
252 }
253 tracer->CloseWithMicroseconds(0);
254 }
255
256 /**
257 * @brief Global Tracer singleton may be placed in .h header and
258 * shared across different compilation units. All would get the
259 * same object.
260 *
261 * @return Single global tracer instance.
262 */
263 static OPENTELEMETRY_NAMESPACE::trace::TracerProvider& GetGlobalTracerProvider()
264 {
265 static exporter::etw::TracerProvider tp
266 ({
267 {"enableTraceId", true},
268 {"enableSpanId", true},
269 {"enableActivityId", true},
270 {"enableRelatedActivityId", true},
271 {"enableAutoParent", true}
272 });
273 return tp;
274 }
275
276 static OPENTELEMETRY_NAMESPACE::trace::Tracer& GetGlobalTracer()
277 {
278 static auto tracer = GetGlobalTracerProvider().GetTracer(kGlobalProviderName);
279 return (*tracer.get());
280 }
281
282 TEST(ETWTracer, GlobalSingletonTracer)
283 {
284 // Obtain a global tracer using C++11 magic static.
285 auto& globalTracer = GetGlobalTracer();
286 auto s1 = globalTracer.StartSpan("Span1");
287 auto traceId1 = s1->GetContext().trace_id();
288 s1->End();
289 /* === Span 1 - "TraceId": "182a64258fb1864ca4e1a542eecbd9bf"
290 {
291 "Timestamp": "2021-05-10T11:45:27.028827-07:00",
292 "ProviderName": "OpenTelemetry-ETW-TLD",
293 "Id": 5,
294 "Message": null,
295 "ProcessId": 23712,
296 "Level": "Always",
297 "Keywords": "0x0000000000000000",
298 "EventName": "Span",
299 "ActivityID": "6ed94703-6b0a-4e76-0000-000000000000",
300 "RelatedActivityID": null,
301 "Payload": {
302 "Duration": 0,
303 "Kind": 1,
304 "Name": "Span1",
305 "SpanId": "0347d96e0a6b764e",
306 "StartTime": "2021-05-10T18:45:27.028000Z",
307 "StatusCode": 0,
308 "StatusMessage": "",
309 "Success": "True",
310 "TraceId": "182a64258fb1864ca4e1a542eecbd9bf",
311 "_name": "Span"
312 }
313 }
314 */
315
316 // Obtain a different tracer withs its own trace-id.
317 auto localTracer = GetGlobalTracerProvider().GetTracer(kGlobalProviderName);
318 auto s2 = localTracer->StartSpan("Span2");
319 auto traceId2 = s2->GetContext().trace_id();
320 s2->End();
321 /* === Span 2 - "TraceId": "334bf9a1eed98d40a873a606295a9368"
322 {
323 "Timestamp": "2021-05-10T11:45:27.0289654-07:00",
324 "ProviderName": "OpenTelemetry-ETW-TLD",
325 "Id": 5,
326 "Message": null,
327 "ProcessId": 23712,
328 "Level": "Always",
329 "Keywords": "0x0000000000000000",
330 "EventName": "Span",
331 "ActivityID": "3b7b2ecb-2e84-4903-0000-000000000000",
332 "RelatedActivityID": null,
333 "Payload": {
334 "Duration": 0,
335 "Kind": 1,
336 "Name": "Span2",
337 "SpanId": "cb2e7b3b842e0349",
338 "StartTime": "2021-05-10T18:45:27.028000Z",
339 "StatusCode": 0,
340 "StatusMessage": "",
341 "Success": "True",
342 "TraceId": "334bf9a1eed98d40a873a606295a9368",
343 "_name": "Span"
344 }
345 }
346 */
347
348 // Obtain the same global tracer with the same trace-id as before.
349 auto& globalTracer2 = GetGlobalTracer();
350 auto s3 = globalTracer2.StartSpan("Span3");
351 auto traceId3 = s3->GetContext().trace_id();
352 s3->End();
353 /* === Span 3 - "TraceId": "182a64258fb1864ca4e1a542eecbd9bf"
354 {
355 "Timestamp": "2021-05-10T11:45:27.0290936-07:00",
356 "ProviderName": "OpenTelemetry-ETW-TLD",
357 "Id": 5,
358 "Message": null,
359 "ProcessId": 23712,
360 "Level": "Always",
361 "Keywords": "0x0000000000000000",
362 "EventName": "Span",
363 "ActivityID": "0a970247-ba0e-4d4b-0000-000000000000",
364 "RelatedActivityID": null,
365 "Payload": {
366 "Duration": 1,
367 "Kind": 1,
368 "Name": "Span3",
369 "SpanId": "4702970a0eba4b4d",
370 "StartTime": "2021-05-10T18:45:27.028000Z",
371 "StatusCode": 0,
372 "StatusMessage": "",
373 "Success": "True",
374 "TraceId": "182a64258fb1864ca4e1a542eecbd9bf",
375 "_name": "Span"
376 }
377 }
378 */
379 EXPECT_NE(traceId1, traceId2);
380 EXPECT_EQ(traceId1, traceId3);
381
382 localTracer->CloseWithMicroseconds(0);
383 globalTracer.CloseWithMicroseconds(0);
384 }
385
386 /* clang-format on */
387
388 #endif