/src/pdns/pdns/dnsdistdist/protozero-trace.cc
Line | Count | Source |
1 | | /* |
2 | | * This file is part of PowerDNS or dnsdist. |
3 | | * Copyright -- PowerDNS.COM B.V. and its contributors |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of version 2 of the GNU General Public License as |
7 | | * published by the Free Software Foundation. |
8 | | * |
9 | | * In addition, for the avoidance of any doubt, permission is granted to |
10 | | * link this program with OpenSSL and to (re)distribute the binaries |
11 | | * produced as the result of such linking. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
21 | | */ |
22 | | |
23 | | #include "protozero-trace.hh" |
24 | | #include "base64.hh" |
25 | | #include "ednsoptions.hh" |
26 | | #include "misc.hh" |
27 | | #include <string> |
28 | | #include <variant> |
29 | | |
30 | | namespace pdns::trace |
31 | | { |
32 | | |
33 | | void AnyValue::encode(protozero::pbf_writer& writer) const |
34 | 0 | { |
35 | 0 | if (std::holds_alternative<std::string>(*this)) { |
36 | 0 | pdns::trace::encode(writer, 1, std::get<std::string>(*this), true); |
37 | 0 | } |
38 | 0 | else if (std::holds_alternative<bool>(*this)) { |
39 | 0 | pdns::trace::encode(writer, 2, std::get<bool>(*this), true); |
40 | 0 | } |
41 | 0 | else if (std::holds_alternative<int64_t>(*this)) { |
42 | 0 | pdns::trace::encode(writer, 3, std::get<int64_t>(*this), true); |
43 | 0 | } |
44 | 0 | else if (std::holds_alternative<double>(*this)) { |
45 | 0 | pdns::trace::encode(writer, 4, std::get<double>(*this), true); |
46 | 0 | } |
47 | 0 | else if (std::holds_alternative<ArrayValue>(*this)) { |
48 | 0 | protozero::pbf_writer sub{writer, 5}; |
49 | 0 | std::get<ArrayValue>(*this).encode(sub); |
50 | 0 | } |
51 | 0 | else if (std::holds_alternative<KeyValueList>(*this)) { |
52 | 0 | protozero::pbf_writer sub{writer, 6}; |
53 | 0 | std::get<KeyValueList>(*this).encode(sub); |
54 | 0 | } |
55 | 0 | else if (std::holds_alternative<std::vector<uint8_t>>(*this)) { |
56 | 0 | pdns::trace::encode(writer, 7, std::get<std::vector<uint8_t>>(*this), true); |
57 | 0 | } |
58 | 0 | } |
59 | | |
60 | | AnyValue AnyValue::decode(protozero::pbf_reader& reader) |
61 | 0 | { |
62 | 0 | while (reader.next()) { |
63 | 0 | switch (reader.tag()) { |
64 | 0 | case 1: |
65 | 0 | return AnyValue{reader.get_string()}; |
66 | 0 | break; |
67 | 0 | case 2: |
68 | 0 | return AnyValue{reader.get_bool()}; |
69 | 0 | break; |
70 | 0 | case 3: |
71 | 0 | return AnyValue{reader.get_int64()}; |
72 | 0 | break; |
73 | 0 | case 4: |
74 | 0 | return AnyValue{reader.get_double()}; |
75 | 0 | break; |
76 | 0 | case 5: { |
77 | 0 | protozero::pbf_reader arrayvalue = reader.get_message(); |
78 | 0 | return AnyValue{ArrayValue::decode(arrayvalue)}; |
79 | 0 | break; |
80 | 0 | } |
81 | 0 | case 6: { |
82 | 0 | protozero::pbf_reader kvlist = reader.get_message(); |
83 | 0 | return AnyValue{KeyValueList::decode(kvlist)}; |
84 | 0 | break; |
85 | 0 | } |
86 | 0 | case 7: { |
87 | 0 | auto value = reader.get_view(); |
88 | 0 | std::vector<uint8_t> data{}; |
89 | 0 | data.reserve(value.size()); |
90 | 0 | for (size_t i = 0; i < value.size(); ++i) { |
91 | 0 | data.push_back(static_cast<uint8_t>(value.data()[i])); |
92 | 0 | } |
93 | 0 | return AnyValue{std::move(data)}; |
94 | 0 | break; |
95 | 0 | } |
96 | 0 | default: |
97 | 0 | break; |
98 | 0 | } |
99 | 0 | } |
100 | | |
101 | 0 | return {}; |
102 | 0 | } |
103 | | |
104 | | std::string AnyValue::toLogString() const |
105 | 0 | { |
106 | 0 | if (std::holds_alternative<std::string>(*this)) { |
107 | 0 | return "\"" + std::get<std::string>(*this) + "\""; |
108 | 0 | } |
109 | 0 | if (std::holds_alternative<bool>(*this)) { |
110 | 0 | if (std::get<bool>(*this)) { |
111 | 0 | return "true"; |
112 | 0 | } |
113 | 0 | return "false"; |
114 | 0 | } |
115 | 0 | if (std::holds_alternative<int64_t>(*this)) { |
116 | 0 | return std::to_string(std::get<int64_t>(*this)); |
117 | 0 | } |
118 | 0 | if (std::holds_alternative<double>(*this)) { |
119 | 0 | return std::to_string(std::get<double>(*this)); |
120 | 0 | } |
121 | 0 | if (std::holds_alternative<ArrayValue>(*this)) { |
122 | 0 | std::string tmp = "["; |
123 | 0 | for (auto const& val : std::get<ArrayValue>(*this).values) { |
124 | 0 | tmp += val.toLogString() + ", "; |
125 | 0 | } |
126 | 0 | tmp.resize(tmp.size() - 2); // Strip ", " |
127 | 0 | return tmp += "]"; |
128 | 0 | } |
129 | 0 | if (std::holds_alternative<KeyValueList>(*this)) { |
130 | 0 | std::string tmp = "{"; |
131 | 0 | for (auto const& val : std::get<KeyValueList>(*this).values) { |
132 | 0 | tmp += val.key + ": " + val.value.toLogString() + ", "; |
133 | 0 | } |
134 | 0 | if (tmp.size() > 2) { |
135 | 0 | tmp.resize(tmp.size() - 2); // Strip ", " |
136 | 0 | } |
137 | 0 | return tmp += "}"; |
138 | 0 | } |
139 | 0 | if (std::holds_alternative<std::vector<uint8_t>>(*this)) { |
140 | 0 | auto val = std::get<std::vector<uint8_t>>(*this); |
141 | 0 | return Base64Encode(std::string(val.begin(), val.end())); |
142 | 0 | } |
143 | 0 | return "UNSUPPORTED TYPE"; |
144 | 0 | } |
145 | | |
146 | | void EntityRef::encode(protozero::pbf_writer& writer) const |
147 | 0 | { |
148 | 0 | pdns::trace::encode(writer, 1, schema_url); |
149 | 0 | pdns::trace::encode(writer, 2, type); |
150 | 0 | for (auto const& element : id_keys) { |
151 | 0 | pdns::trace::encode(writer, 3, element); |
152 | 0 | } |
153 | 0 | for (auto const& element : description_keys) { |
154 | 0 | pdns::trace::encode(writer, 4, element); |
155 | 0 | } |
156 | 0 | } |
157 | | |
158 | | EntityRef EntityRef::decode(protozero::pbf_reader& reader) |
159 | 0 | { |
160 | 0 | EntityRef ret; |
161 | 0 | while (reader.next()) { |
162 | 0 | switch (reader.tag()) { |
163 | 0 | case 1: |
164 | 0 | ret.schema_url = reader.get_string(); |
165 | 0 | break; |
166 | 0 | case 2: |
167 | 0 | ret.type = reader.get_string(); |
168 | 0 | break; |
169 | 0 | case 3: |
170 | 0 | ret.id_keys.emplace_back(reader.get_string()); |
171 | 0 | break; |
172 | 0 | case 4: |
173 | 0 | ret.description_keys.emplace_back(reader.get_string()); |
174 | 0 | break; |
175 | 0 | default: |
176 | 0 | break; |
177 | 0 | } |
178 | 0 | } |
179 | 0 | return ret; |
180 | 0 | } |
181 | | |
182 | | bool EntityRef::operator==(const EntityRef& rhs) const |
183 | 0 | { |
184 | 0 | return (schema_url == rhs.schema_url && type == rhs.type && id_keys == rhs.id_keys && description_keys == rhs.description_keys); |
185 | 0 | } |
186 | | |
187 | | void KeyValue::encode(protozero::pbf_writer& writer) const |
188 | 0 | { |
189 | 0 | pdns::trace::encode(writer, 1, key); |
190 | 0 | { |
191 | 0 | protozero::pbf_writer val_sub{writer, 2}; |
192 | 0 | value.encode(val_sub); |
193 | 0 | } |
194 | 0 | } |
195 | | |
196 | | void Resource::encode(protozero::pbf_writer& writer) const |
197 | 0 | { |
198 | 0 | pdns::trace::encode(writer, 1, attributes); |
199 | 0 | pdns::trace::encode(writer, 2, dropped_attributes_count); |
200 | 0 | pdns::trace::encode(writer, 3, entity_refs); |
201 | 0 | } |
202 | | |
203 | | Resource Resource::decode(protozero::pbf_reader& reader) |
204 | 0 | { |
205 | 0 | Resource ret; |
206 | 0 | while (reader.next()) { |
207 | 0 | switch (reader.tag()) { |
208 | 0 | case 1: { |
209 | 0 | auto sub = reader.get_message(); |
210 | 0 | ret.attributes.emplace_back(KeyValue::decode(sub)); |
211 | 0 | break; |
212 | 0 | } |
213 | 0 | case 2: |
214 | 0 | ret.dropped_attributes_count = reader.get_uint32(); |
215 | 0 | break; |
216 | 0 | case 3: { |
217 | 0 | auto sub = reader.get_message(); |
218 | 0 | ret.entity_refs.emplace_back(EntityRef::decode(sub)); |
219 | 0 | break; |
220 | 0 | } |
221 | 0 | default: |
222 | 0 | break; |
223 | 0 | } |
224 | 0 | } |
225 | 0 | return ret; |
226 | 0 | } |
227 | | |
228 | | bool Resource::operator==(const Resource& rhs) const |
229 | 0 | { |
230 | 0 | return (attributes == rhs.attributes && dropped_attributes_count == rhs.dropped_attributes_count && entity_refs == rhs.entity_refs); |
231 | 0 | } |
232 | | |
233 | | void InstrumentationScope::encode(protozero::pbf_writer& writer) const |
234 | 0 | { |
235 | 0 | pdns::trace::encode(writer, 1, name); |
236 | 0 | pdns::trace::encode(writer, 2, version); |
237 | 0 | pdns::trace::encode(writer, 3, attributes); |
238 | 0 | pdns::trace::encode(writer, 4, dropped_attributes_count); |
239 | 0 | } |
240 | | |
241 | | InstrumentationScope InstrumentationScope::decode(protozero::pbf_reader& reader) |
242 | 0 | { |
243 | 0 | InstrumentationScope ret; |
244 | 0 | while (reader.next()) { |
245 | 0 | switch (reader.tag()) { |
246 | 0 | case 1: |
247 | 0 | ret.name = reader.get_string(); |
248 | 0 | break; |
249 | 0 | case 2: |
250 | 0 | ret.version = reader.get_string(); |
251 | 0 | break; |
252 | 0 | case 3: { |
253 | 0 | auto sub = reader.get_message(); |
254 | 0 | ret.attributes.emplace_back(KeyValue::decode(sub)); |
255 | 0 | break; |
256 | 0 | } |
257 | 0 | case 4: |
258 | 0 | ret.dropped_attributes_count = reader.get_uint32(); |
259 | 0 | break; |
260 | 0 | default: |
261 | 0 | break; |
262 | 0 | } |
263 | 0 | } |
264 | 0 | return ret; |
265 | 0 | } |
266 | | |
267 | | bool InstrumentationScope::operator==(const InstrumentationScope& rhs) const |
268 | 0 | { |
269 | 0 | return (name == rhs.name && version == rhs.version && attributes == rhs.attributes && dropped_attributes_count == rhs.dropped_attributes_count); |
270 | 0 | } |
271 | | |
272 | | void Status::encode(protozero::pbf_writer& writer) const |
273 | 0 | { |
274 | 0 | pdns::trace::encode(writer, 2, message); |
275 | 0 | pdns::trace::encode(writer, 3, uint32_t(code)); |
276 | 0 | } |
277 | | |
278 | | Status Status::decode(protozero::pbf_reader& reader) |
279 | 0 | { |
280 | 0 | Status ret; |
281 | 0 | while (reader.next()) { |
282 | 0 | switch (reader.tag()) { |
283 | 0 | case 2: |
284 | 0 | ret.message = reader.get_string(); |
285 | 0 | break; |
286 | 0 | case 3: |
287 | 0 | ret.code = static_cast<StatusCode>(reader.get_uint32()); |
288 | 0 | break; |
289 | 0 | default: |
290 | 0 | break; |
291 | 0 | } |
292 | 0 | } |
293 | 0 | return ret; |
294 | 0 | } |
295 | | |
296 | | bool Status::operator==(const Status& rhs) const |
297 | 0 | { |
298 | 0 | return (message == rhs.message && code == rhs.code); |
299 | 0 | } |
300 | | |
301 | | void Span::Event::encode(protozero::pbf_writer& writer) const |
302 | 0 | { |
303 | 0 | pdns::trace::encodeFixed(writer, 1, time_unix_nano); |
304 | 0 | pdns::trace::encode(writer, 2, name); |
305 | 0 | pdns::trace::encode(writer, 3, attributes); |
306 | 0 | pdns::trace::encode(writer, 4, dropped_attributes_count); |
307 | 0 | } |
308 | | |
309 | | Span::Event Span::Event::decode(protozero::pbf_reader& reader) |
310 | 0 | { |
311 | 0 | Span::Event ret; |
312 | 0 | while (reader.next()) { |
313 | 0 | switch (reader.tag()) { |
314 | 0 | case 1: |
315 | 0 | ret.time_unix_nano = reader.get_fixed64(); |
316 | 0 | break; |
317 | 0 | case 2: |
318 | 0 | ret.name = reader.get_string(); |
319 | 0 | break; |
320 | 0 | case 3: { |
321 | 0 | auto sub = reader.get_message(); |
322 | 0 | ret.attributes.emplace_back(KeyValue::decode(sub)); |
323 | 0 | break; |
324 | 0 | } |
325 | 0 | case 4: |
326 | 0 | ret.dropped_attributes_count = reader.get_uint32(); |
327 | 0 | default: |
328 | 0 | break; |
329 | 0 | } |
330 | 0 | } |
331 | 0 | return ret; |
332 | 0 | } |
333 | | |
334 | | bool Span::Event::operator==(const Span::Event& rhs) const |
335 | 0 | { |
336 | 0 | return (time_unix_nano == rhs.time_unix_nano && name == rhs.name && attributes == rhs.attributes && dropped_attributes_count == rhs.dropped_attributes_count); |
337 | 0 | } |
338 | | |
339 | | void Span::Link::encode(protozero::pbf_writer& writer) const |
340 | 0 | { |
341 | 0 | pdns::trace::encode(writer, 1, trace_id); |
342 | 0 | pdns::trace::encode(writer, 2, span_id); |
343 | 0 | pdns::trace::encode(writer, 3, trace_state); |
344 | 0 | pdns::trace::encode(writer, 4, attributes); |
345 | 0 | pdns::trace::encode(writer, 5, dropped_attributes_count); |
346 | 0 | pdns::trace::encodeFixed(writer, 6, flags); |
347 | 0 | } |
348 | | |
349 | | Span::Link Span::Link::decode(protozero::pbf_reader& reader) |
350 | 0 | { |
351 | 0 | Link ret; |
352 | 0 | while (reader.next()) { |
353 | 0 | switch (reader.tag()) { |
354 | 0 | case 1: |
355 | 0 | ret.trace_id = decodeTraceID(reader); |
356 | 0 | break; |
357 | 0 | case 2: |
358 | 0 | ret.span_id = decodeSpanID(reader); |
359 | 0 | break; |
360 | 0 | case 3: |
361 | 0 | ret.trace_state = reader.get_string(); |
362 | 0 | break; |
363 | 0 | case 4: { |
364 | 0 | auto sub = reader.get_message(); |
365 | 0 | ret.attributes.emplace_back(KeyValue::decode(sub)); |
366 | 0 | break; |
367 | 0 | } |
368 | 0 | case 5: |
369 | 0 | ret.dropped_attributes_count = reader.get_uint32(); |
370 | 0 | break; |
371 | 0 | case 6: |
372 | 0 | ret.flags = reader.get_fixed32(); |
373 | 0 | default: |
374 | 0 | break; |
375 | 0 | } |
376 | 0 | } |
377 | 0 | return ret; |
378 | 0 | } |
379 | | |
380 | | bool Span::Link::operator==(const Span::Link& rhs) const |
381 | 0 | { |
382 | 0 | return (trace_id == rhs.trace_id && span_id == rhs.span_id && trace_state == rhs.trace_state && attributes == rhs.attributes && dropped_attributes_count == rhs.dropped_attributes_count && flags == rhs.flags); |
383 | 0 | } |
384 | | |
385 | | void Span::encode(protozero::pbf_writer& writer) const |
386 | 0 | { |
387 | 0 | pdns::trace::encode(writer, 1, trace_id); |
388 | 0 | pdns::trace::encode(writer, 2, span_id); |
389 | 0 | pdns::trace::encode(writer, 3, trace_state); |
390 | 0 | pdns::trace::encode(writer, 4, parent_span_id); |
391 | 0 | pdns::trace::encode(writer, 5, name); |
392 | 0 | pdns::trace::encode(writer, 6, uint32_t(kind)); |
393 | 0 | pdns::trace::encodeFixed(writer, 7, start_time_unix_nano); |
394 | 0 | pdns::trace::encodeFixed(writer, 8, end_time_unix_nano); |
395 | 0 | pdns::trace::encode(writer, 9, attributes); |
396 | 0 | pdns::trace::encode(writer, 10, dropped_attributes_count); |
397 | 0 | pdns::trace::encode(writer, 11, events); |
398 | 0 | pdns::trace::encode(writer, 12, dropped_events_count); |
399 | 0 | pdns::trace::encode(writer, 13, links); |
400 | 0 | pdns::trace::encode(writer, 14, dropped_links_count); |
401 | 0 | if (status.code != Status::StatusCode::STATUS_CODE_UNSET || !status.message.empty()) { |
402 | 0 | protozero::pbf_writer sub{writer, 15}; |
403 | 0 | status.encode(sub); |
404 | 0 | } |
405 | 0 | pdns::trace::encodeFixed(writer, 16, flags); |
406 | 0 | } |
407 | | |
408 | | Span Span::decode(protozero::pbf_reader& reader) |
409 | 0 | { |
410 | 0 | Span ret; |
411 | 0 | while (reader.next()) { |
412 | 0 | switch (reader.tag()) { |
413 | 0 | case 1: |
414 | 0 | ret.trace_id = decodeTraceID(reader); |
415 | 0 | break; |
416 | 0 | case 2: |
417 | 0 | ret.span_id = decodeSpanID(reader); |
418 | 0 | break; |
419 | 0 | case 3: |
420 | 0 | ret.trace_state = reader.get_string(); |
421 | 0 | break; |
422 | 0 | case 4: |
423 | 0 | ret.parent_span_id = decodeSpanID(reader); |
424 | 0 | break; |
425 | 0 | case 5: |
426 | 0 | ret.name = reader.get_string(); |
427 | 0 | break; |
428 | 0 | case 6: |
429 | 0 | ret.kind = static_cast<Span::SpanKind>(reader.get_uint32()); |
430 | 0 | break; |
431 | 0 | case 7: |
432 | 0 | ret.start_time_unix_nano = reader.get_fixed64(); |
433 | 0 | break; |
434 | 0 | case 8: |
435 | 0 | ret.end_time_unix_nano = reader.get_fixed64(); |
436 | 0 | break; |
437 | 0 | case 9: { |
438 | 0 | auto sub = reader.get_message(); |
439 | 0 | ret.attributes.emplace_back(KeyValue::decode(sub)); |
440 | 0 | break; |
441 | 0 | } |
442 | 0 | case 10: |
443 | 0 | ret.dropped_attributes_count = reader.get_uint32(); |
444 | 0 | break; |
445 | 0 | case 11: { |
446 | 0 | auto sub = reader.get_message(); |
447 | 0 | ret.events.emplace_back(Span::Event::decode(sub)); |
448 | 0 | break; |
449 | 0 | } |
450 | 0 | case 12: |
451 | 0 | ret.dropped_events_count = reader.get_uint32(); |
452 | 0 | break; |
453 | 0 | case 13: { |
454 | 0 | auto sub = reader.get_message(); |
455 | 0 | ret.links.emplace_back(Span::Link::decode(sub)); |
456 | 0 | break; |
457 | 0 | } |
458 | 0 | case 14: |
459 | 0 | ret.dropped_links_count = reader.get_uint32(); |
460 | 0 | break; |
461 | 0 | case 15: { |
462 | 0 | auto sub = reader.get_message(); |
463 | 0 | ret.status = Status::decode(sub); |
464 | 0 | break; |
465 | 0 | } |
466 | 0 | case 16: |
467 | 0 | ret.flags = reader.get_fixed32(); |
468 | 0 | break; |
469 | 0 | default: |
470 | 0 | break; |
471 | 0 | } |
472 | 0 | } |
473 | 0 | return ret; |
474 | 0 | } |
475 | | |
476 | | bool Span::operator==(const Span& rhs) const |
477 | 0 | { |
478 | 0 | return (trace_id == rhs.trace_id && span_id == rhs.span_id && trace_state == rhs.trace_state && parent_span_id == rhs.parent_span_id && name == rhs.name && kind == rhs.kind && start_time_unix_nano == rhs.start_time_unix_nano && end_time_unix_nano == rhs.end_time_unix_nano && attributes == rhs.attributes && dropped_attributes_count == rhs.dropped_attributes_count && events == rhs.events && dropped_events_count == rhs.dropped_events_count && links == rhs.links && dropped_links_count == rhs.dropped_links_count && status == rhs.status && flags == rhs.flags); |
479 | 0 | } |
480 | | |
481 | | void ScopeSpans::encode(protozero::pbf_writer& writer) const |
482 | 0 | { |
483 | 0 | { |
484 | 0 | protozero::pbf_writer sub{writer, 1}; |
485 | 0 | scope.encode(sub); |
486 | 0 | } |
487 | 0 | pdns::trace::encode(writer, 2, spans); |
488 | 0 | pdns::trace::encode(writer, 3, schema_url); |
489 | 0 | } |
490 | | |
491 | | ScopeSpans ScopeSpans::decode(protozero::pbf_reader& reader) |
492 | 0 | { |
493 | 0 | ScopeSpans ret; |
494 | 0 | while (reader.next()) { |
495 | 0 | switch (reader.tag()) { |
496 | 0 | case 1: { |
497 | 0 | auto sub = reader.get_message(); |
498 | 0 | ret.scope = InstrumentationScope::decode(sub); |
499 | 0 | break; |
500 | 0 | } |
501 | 0 | case 2: { |
502 | 0 | auto sub = reader.get_message(); |
503 | 0 | ret.spans.emplace_back(Span::decode(sub)); |
504 | 0 | break; |
505 | 0 | } |
506 | 0 | case 3: |
507 | 0 | ret.schema_url = reader.get_string(); |
508 | 0 | default: |
509 | 0 | break; |
510 | 0 | } |
511 | 0 | } |
512 | 0 | return ret; |
513 | 0 | } |
514 | | |
515 | | bool ScopeSpans::operator==(const ScopeSpans& rhs) const |
516 | 0 | { |
517 | 0 | return (scope == rhs.scope && spans == rhs.spans && schema_url == rhs.schema_url); |
518 | 0 | } |
519 | | |
520 | | void ResourceSpans::encode(protozero::pbf_writer& writer) const |
521 | 0 | { |
522 | 0 | { |
523 | 0 | protozero::pbf_writer sub{writer, 1}; |
524 | 0 | resource.encode(sub); |
525 | 0 | } |
526 | 0 | pdns::trace::encode(writer, 2, scope_spans); |
527 | 0 | pdns::trace::encode(writer, 3, schema_url); |
528 | 0 | } |
529 | | |
530 | | ResourceSpans ResourceSpans::decode(protozero::pbf_reader& reader) |
531 | 0 | { |
532 | 0 | ResourceSpans ret; |
533 | 0 | while (reader.next()) { |
534 | 0 | switch (reader.tag()) { |
535 | 0 | case 1: { |
536 | 0 | protozero::pbf_reader sub = reader.get_message(); |
537 | 0 | ret.resource = Resource::decode(sub); |
538 | 0 | break; |
539 | 0 | } |
540 | 0 | case 2: { |
541 | 0 | protozero::pbf_reader sub = reader.get_message(); |
542 | 0 | ret.scope_spans.emplace_back(ScopeSpans::decode(sub)); |
543 | 0 | break; |
544 | 0 | } |
545 | 0 | case 3: |
546 | 0 | ret.schema_url = reader.get_string(); |
547 | 0 | default: |
548 | 0 | break; |
549 | 0 | } |
550 | 0 | } |
551 | 0 | return ret; |
552 | 0 | } |
553 | | |
554 | | bool ResourceSpans::operator==(const ResourceSpans& rhs) const |
555 | 0 | { |
556 | 0 | return (resource == rhs.resource && scope_spans == rhs.scope_spans && schema_url == rhs.schema_url); |
557 | 0 | } |
558 | | |
559 | | void TracesData::encode(protozero::pbf_writer& writer) const |
560 | 0 | { |
561 | 0 | pdns::trace::encode(writer, 1, resource_spans); |
562 | 0 | } |
563 | | |
564 | | TracesData TracesData::decode(protozero::pbf_reader& reader) |
565 | 0 | { |
566 | 0 | TracesData ret; |
567 | 0 | while (reader.next()) { |
568 | 0 | switch (reader.tag()) { |
569 | 0 | case 1: { |
570 | 0 | auto sub = reader.get_message(); |
571 | 0 | ret.resource_spans.emplace_back(ResourceSpans::decode(sub)); |
572 | 0 | break; |
573 | 0 | } |
574 | 0 | default: |
575 | 0 | break; |
576 | 0 | } |
577 | 0 | } |
578 | 0 | return ret; |
579 | 0 | } |
580 | | |
581 | | KeyValue KeyValue::decode(protozero::pbf_reader& reader) |
582 | 0 | { |
583 | 0 | KeyValue value; |
584 | 0 | while (reader.next()) { |
585 | 0 | switch (reader.tag()) { |
586 | 0 | case 1: |
587 | 0 | value.key = reader.get_string(); |
588 | 0 | break; |
589 | 0 | case 2: { |
590 | 0 | protozero::pbf_reader sub = reader.get_message(); |
591 | 0 | value.value = AnyValue::decode(sub); |
592 | 0 | break; |
593 | 0 | } |
594 | 0 | default: |
595 | 0 | break; |
596 | 0 | } |
597 | 0 | } |
598 | 0 | return value; |
599 | 0 | } |
600 | | |
601 | | bool extractOTraceIDs(const EDNSOptionViewMap& map, EDNSOptionCode::EDNSOptionCodeEnum eoc, pdns::trace::InitialSpanInfo& span) |
602 | 0 | { |
603 | | // traceid gets set from edns options (if available and well-formed) |
604 | | // parent_span_id gets set from edns options (if available and well-formed) |
605 | 0 | auto traceidset = extractOTraceIDs(map, eoc, span.trace_id, span.parent_span_id); |
606 | 0 | return traceidset; |
607 | 0 | } |
608 | | |
609 | | /** |
610 | | * @brief Extract the Trace and Span IDs from |
611 | | * |
612 | | * @param map an EDNSOptionViewMap where a TraceID option might be |
613 | | * @param eoc the EDNS option code where the TraceID might be, OTTRACEIDS by default |
614 | | * @param traceID will be set to the TraceID in the EDNS option, untouched otherwise |
615 | | * @param spanID will be set to the SpanID in the EDNS options, untouched otherwise |
616 | | * @return true if a traceid was found in the EDNS options |
617 | | */ |
618 | | bool extractOTraceIDs(const EDNSOptionViewMap& map, EDNSOptionCode::EDNSOptionCodeEnum eoc, pdns::trace::TraceID& traceID, pdns::trace::SpanID& spanID) |
619 | 0 | { |
620 | 0 | EDNSOptionCode::EDNSOptionCodeEnum realEOC = eoc; |
621 | 0 | if (realEOC == 0) { |
622 | 0 | realEOC = EDNSOptionCode::TRACEPARENT; |
623 | 0 | } |
624 | 0 | bool traceidset = false; |
625 | 0 | if (const auto& option = map.find(realEOC); option != map.end()) { |
626 | 0 | const auto& value = option->second.values.at(0); |
627 | 0 | const EDNSOTTraceRecordView data{reinterpret_cast<const uint8_t*>(value.content), value.size}; // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) |
628 | | // 1 byte version, then tracid then optional spanid |
629 | 0 | uint8_t version{}; |
630 | 0 | if (data.getVersion(version) && version == 0) { |
631 | 0 | if (data.getTraceID(traceID)) { |
632 | 0 | traceidset = true; |
633 | 0 | } |
634 | 0 | (void)data.getSpanID(spanID); |
635 | 0 | } |
636 | 0 | } |
637 | 0 | return traceidset; |
638 | 0 | } |
639 | | |
640 | | std::string SpanID::toLogString() const |
641 | 0 | { |
642 | 0 | return makeHexDump(std::string(this->begin(), this->end()), ""); |
643 | 0 | } |
644 | | |
645 | | std::string TraceID::toLogString() const |
646 | 0 | { |
647 | 0 | return makeHexDump(std::string(this->begin(), this->end()), ""); |
648 | 0 | } |
649 | | |
650 | | } // namespace pdns::trace |