Skip to content

Commit c608269

Browse files
authored
128-bit trace IDs (#17)
1 parent cdb5f23 commit c608269

36 files changed

+824
-215
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
resource_class: small
1717
steps:
1818
- checkout
19-
- run: find bin/ -executable -type f | xargs shellcheck
19+
- run: find bin/ -executable -type f -print0 | xargs -0 shellcheck
2020

2121
build-bazel:
2222
parameters:

BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ cc_library(
4747
"src/datadog/threaded_event_scheduler.cpp",
4848
"src/datadog/tracer_config.cpp",
4949
"src/datadog/tracer.cpp",
50+
"src/datadog/trace_id.cpp",
5051
"src/datadog/trace_sampler_config.cpp",
5152
"src/datadog/trace_sampler.cpp",
5253
"src/datadog/trace_segment.cpp",
@@ -101,6 +102,7 @@ cc_library(
101102
"src/datadog/threaded_event_scheduler.h",
102103
"src/datadog/tracer_config.h",
103104
"src/datadog/tracer.h",
105+
"src/datadog/trace_id.h",
104106
"src/datadog/trace_sampler_config.h",
105107
"src/datadog/trace_sampler.h",
106108
"src/datadog/trace_segment.h",

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ target_sources(dd_trace_cpp PRIVATE
116116
src/datadog/threaded_event_scheduler.cpp
117117
src/datadog/tracer_config.cpp
118118
src/datadog/tracer.cpp
119+
src/datadog/trace_id.cpp
119120
src/datadog/trace_sampler_config.cpp
120121
src/datadog/trace_sampler.cpp
121122
src/datadog/trace_segment.cpp
@@ -176,6 +177,7 @@ target_sources(dd_trace_cpp PUBLIC
176177
src/datadog/threaded_event_scheduler.h
177178
src/datadog/tracer_config.h
178179
src/datadog/tracer.h
180+
src/datadog/trace_id.h
179181
src/datadog/trace_sampler_config.h
180182
src/datadog/trace_sampler.h
181183
src/datadog/trace_segment.h

bin/check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ cd "$(dirname "$0")"/..
1111
bin/format --dry-run -Werror
1212
bin/test
1313
bin/bazel-build
14+
find bin/ -executable -type f -print0 | xargs -0 shellcheck

src/datadog/environment.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ namespace environment {
4646
MACRO(DD_TRACE_SAMPLING_RULES) \
4747
MACRO(DD_TRACE_STARTUP_LOGS) \
4848
MACRO(DD_TRACE_TAGS_PROPAGATION_MAX_LENGTH) \
49-
MACRO(DD_VERSION)
49+
MACRO(DD_VERSION) \
50+
MACRO(DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
5051

5152
#define WITH_COMMA(ARG) ARG,
5253

src/datadog/extracted_data.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,17 @@
99
#include <vector>
1010

1111
#include "optional.h"
12+
#include "trace_id.h"
1213

1314
namespace datadog {
1415
namespace tracing {
1516

1617
struct ExtractedData {
17-
Optional<std::uint64_t> trace_id;
18+
Optional<TraceID> trace_id;
1819
Optional<std::uint64_t> parent_id;
1920
Optional<std::string> origin;
2021
std::vector<std::pair<std::string, std::string>> trace_tags;
2122
Optional<int> sampling_priority;
22-
// If this `ExtractedData` was created on account of `PropagationStyle::W3C`
23-
// and trace context was successfully extracted, then `full_w3c_trace_id_hex`
24-
// contains the hex-encoded 128-bit trace ID. `trace_id` will be the least
25-
// significant 64 bits of the same value. `full_w3c_trace_id_hex` is used for
26-
// the `W3C` injection style.
27-
Optional<std::string> full_w3c_trace_id_hex;
2823
// If this `ExtractedData` was created on account of `PropagationStyle::W3C`,
2924
// then `additional_w3c_tracestate` contains the parts of the "tracestate"
3025
// header that are not the "dd" (Datadog) entry. If there are no other parts,

src/datadog/hex.h

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
// This component provides a function, `hex`, for formatting an integral value
3+
// This component provides functions for formatting an unsigned integral value
44
// in hexadecimal.
55

66
#include <cassert>
@@ -12,12 +12,14 @@
1212
namespace datadog {
1313
namespace tracing {
1414

15-
// Return the specified `value` formatted as a lower-case hexadecimal string
16-
// without any leading zeroes.
17-
template <typename Integer>
18-
std::string hex(Integer value) {
19-
// 4 bits per hex digit char, and then +1 char for possible minus sign
20-
char buffer[std::numeric_limits<Integer>::digits / 4 + 1];
15+
// Return the specified unsigned `value` formatted as a lower-case hexadecimal
16+
// string without any leading zeroes.
17+
template <typename UnsignedInteger>
18+
std::string hex(UnsignedInteger value) {
19+
static_assert(!std::numeric_limits<UnsignedInteger>::is_signed);
20+
21+
// 4 bits per hex digit char
22+
char buffer[std::numeric_limits<UnsignedInteger>::digits / 4];
2123

2224
const int base = 16;
2325
auto result =
@@ -27,5 +29,25 @@ std::string hex(Integer value) {
2729
return std::string{std::begin(buffer), result.ptr};
2830
}
2931

32+
// Return the specified unsigned `value` formatted as a lower-case hexadecimal
33+
// string with leading zeroes.
34+
template <typename UnsignedInteger>
35+
std::string hex_padded(UnsignedInteger value) {
36+
static_assert(!std::numeric_limits<UnsignedInteger>::is_signed);
37+
38+
// 4 bits per hex digit char.
39+
char buffer[std::numeric_limits<UnsignedInteger>::digits / 4];
40+
41+
const int base = 16;
42+
auto result =
43+
std::to_chars(std::begin(buffer), std::end(buffer), value, base);
44+
assert(result.ec == std::errc());
45+
46+
const auto num_zeroes = sizeof(buffer) - (result.ptr - std::begin(buffer));
47+
std::string padded(num_zeroes, '0');
48+
padded.append(std::begin(buffer), result.ptr);
49+
return padded;
50+
}
51+
3052
} // namespace tracing
3153
} // namespace datadog

src/datadog/id_generator.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace {
1616
extern "C" void on_fork();
1717
#endif
1818

19-
class DefaultIDGenerator {
19+
class Uint64Generator {
2020
std::mt19937_64 generator_;
2121
// The distribution used is for a _signed_ integer, and the default minimum
2222
// value is zero.
@@ -26,7 +26,7 @@ class DefaultIDGenerator {
2626
std::uniform_int_distribution<std::int64_t> distribution_;
2727

2828
public:
29-
DefaultIDGenerator() {
29+
Uint64Generator() {
3030
seed_with_random();
3131
// If a process links to this library and then calls `fork`, the `generator_` in
3232
// the parent and child processes will produce the exact same sequence of
@@ -48,17 +48,36 @@ class DefaultIDGenerator {
4848
void seed_with_random() { generator_.seed(std::random_device{}()); }
4949
};
5050

51-
thread_local DefaultIDGenerator thread_local_generator;
51+
thread_local Uint64Generator thread_local_generator;
5252

5353
#ifndef _MSC_VER
5454
void on_fork() { thread_local_generator.seed_with_random(); }
5555
#endif
5656

57-
} // namespace
57+
class DefaultIDGenerator : public IDGenerator {
58+
const bool trace_id_128_bit_;
59+
60+
public:
61+
explicit DefaultIDGenerator(bool trace_id_128_bit)
62+
: trace_id_128_bit_(trace_id_128_bit) {}
63+
64+
TraceID trace_id() const override {
65+
TraceID result;
66+
result.low = thread_local_generator();
67+
if (trace_id_128_bit_) {
68+
result.high = thread_local_generator();
69+
}
70+
return result;
71+
}
5872

59-
const IDGenerator default_id_generator = []() {
60-
return thread_local_generator();
73+
std::uint64_t span_id() const override { return thread_local_generator(); }
6174
};
6275

76+
} // namespace
77+
78+
std::shared_ptr<const IDGenerator> default_id_generator(bool trace_id_128_bit) {
79+
return std::make_shared<DefaultIDGenerator>(trace_id_128_bit);
80+
}
81+
6382
} // namespace tracing
6483
} // namespace datadog

src/datadog/id_generator.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,29 @@
33
// This component provides facilities for generating sequences of IDs used as
44
// span IDs and trace IDs.
55
//
6-
// `IDGenerator` is an alias for `std::function<std::uint64_t()>`.
6+
// `IDGenerator` is an interface for generating trace IDs and span IDs.
77
//
88
// `default_id_generator` is an `IDGenerator` that produces a thread-local
99
// pseudo-random sequence of uniformly distributed 63-bit unsigned integers. The
10-
// sequence is randomly seeded one per thread and anytime the process forks.
11-
// The IDs are 63-bit (instead of 64-bit) to ease compatibility with peer
12-
// runtimes that don't have a native 64-bit unsigned numeric type.
10+
// sequence is randomly seeded once per thread and anytime the process forks.
1311

1412
#include <cstdint>
15-
#include <functional>
13+
#include <memory>
14+
15+
#include "trace_id.h"
1616

1717
namespace datadog {
1818
namespace tracing {
1919

20-
using IDGenerator = std::function<std::uint64_t()>;
20+
class IDGenerator {
21+
public:
22+
virtual ~IDGenerator() = default;
23+
24+
virtual std::uint64_t span_id() const = 0;
25+
virtual TraceID trace_id() const = 0;
26+
};
2127

22-
extern const IDGenerator default_id_generator;
28+
std::shared_ptr<const IDGenerator> default_id_generator(bool trace_id_128_bit);
2329

2430
} // namespace tracing
2531
} // namespace datadog

src/datadog/limiter.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#include <algorithm>
44
#include <cmath>
5-
#include <iostream>
65
#include <numeric>
76

87
namespace datadog {

0 commit comments

Comments
 (0)