Coverage Report

Created: 2026-07-16 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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