Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
68850b3
TODO: AMEND: add W3C style, but it doesn't do anything
dgoffredo Dec 19, 2022
8238cd5
TODO: AMEND: untested traceparent extraction
dgoffredo Dec 19, 2022
1a06e86
TODO: AMEND: it's already thread-safe
dgoffredo Dec 20, 2022
122fc3d
add a convenience script that does some of the CI checks
dgoffredo Dec 20, 2022
fea2115
TODO: AMEND: whoops
dgoffredo Dec 20, 2022
aaea195
TODO: AMEND: extract traceparent
dgoffredo Dec 20, 2022
b34231e
TODO: AMEND: add some documentation
dgoffredo Dec 21, 2022
d0005cd
TODO: AMEND: inject traceparent
dgoffredo Dec 21, 2022
5ce2166
TODO: AMEND: untested tracestate extraction
dgoffredo Dec 21, 2022
3158907
TODO: AMEND: tested tracestate extraction
dgoffredo Dec 21, 2022
b69ad49
TODO: AMEND: add some more documentation
dgoffredo Dec 21, 2022
fea6cae
TODO: AMEND: checkpoint
dgoffredo Dec 21, 2022
b1888ec
TODO: AMEND: checkpoint
dgoffredo Dec 21, 2022
6bc3168
TODO: AMEND: checkpoint, before I mess with flat maps
dgoffredo Dec 22, 2022
cf67c0f
TODO: AMEND: trace_tags is a vector
dgoffredo Dec 22, 2022
0cff419
TODO: AMEND: tracestate injection tested
dgoffredo Dec 22, 2022
4e8719d
TODO: AMEND: fix scary typo
dgoffredo Dec 22, 2022
a72b297
TODO: AMEND: update includes graph in doc/
dgoffredo Dec 22, 2022
b3c9fa4
TODO: AMEND: add a fuzzer for W3C propagation
dgoffredo Dec 22, 2022
065945c
TODO: AMEND: thread_local, not that it matters
dgoffredo Dec 22, 2022
3bbf910
TODO: AMEND: document the fuzzer
dgoffredo Dec 22, 2022
dcf6cda
TODO: AMEND: typo in readme
dgoffredo Dec 22, 2022
9a9212c
TODO: AMEND: be honest
dgoffredo Dec 22, 2022
e923b03
shellcheck
dgoffredo Jan 9, 2023
ac95cd1
shellcheck
dgoffredo Jan 9, 2023
f789c1c
tricky rebase...
dgoffredo Jan 9, 2023
46cc7e5
add a class TraceID for future use
dgoffredo Jan 11, 2023
496c0a6
TODO: AMEND: here we go...
dgoffredo Jan 11, 2023
e17d8e4
adjusted existing unit tests
dgoffredo Jan 11, 2023
3ffa4dc
zero, not null
dgoffredo Jan 11, 2023
efe675f
TODO: AMEND: thinking about _dd.p.tid
dgoffredo Jan 11, 2023
62ed713
TODO: AMEND: thinking about _dd.p.tid
dgoffredo Jan 11, 2023
4b177c1
getting there...
dgoffredo Jan 12, 2023
63f2121
Merge branch 'david.goffredo/128-bit-trace-id' of github.com:DataDog/…
dgoffredo Jan 12, 2023
4cadd03
virtual destructor in new interface
dgoffredo Jan 12, 2023
6c88da5
merge in changes make to base branch in code review (david.goffredo/w…
dgoffredo Jan 13, 2023
bdd7548
revert comments removed when I /std::cerr/d earlier
dgoffredo Jan 13, 2023
fc9afaf
tentative: DD_TRACE_ID_128_BIT_ENABLED
dgoffredo Jan 13, 2023
e1c77d6
Merge branch 'main' into david.goffredo/128-bit-trace-id
dgoffredo Jan 13, 2023
3881b27
add shellcheck to bin/check
dgoffredo Jan 16, 2023
dd6509c
test the generation of 128-bit trace IDs
dgoffredo Jan 16, 2023
b3749e1
test the extraction of 128-bit trace IDs
dgoffredo Jan 16, 2023
964bd55
test the injection of 128-bit trace IDs
dgoffredo Jan 16, 2023
f8a4c6b
test the configuration of 128-bit trace IDs
dgoffredo Jan 16, 2023
758bfbf
whoops
dgoffredo Jan 16, 2023
b45b154
remove spurious TODO
dgoffredo Jan 16, 2023
ea014b6
test TraceID::parse_hex
dgoffredo Jan 16, 2023
036c94f
remove unnecessary parsing in test
dgoffredo Jan 17, 2023
c0cd83d
test TraceID comparisons
dgoffredo Jan 17, 2023
1ce7f28
document trace_id.h
dgoffredo Jan 17, 2023
8df560a
cover the rest of the comparison cases
dgoffredo Jan 17, 2023
9841db7
remove spurious TODO
dgoffredo Jan 17, 2023
18aead7
test TraceID serialization
dgoffredo Jan 17, 2023
db9e1da
document what knuth_hash is for, mentioning 128-bit trace IDs
dgoffredo Jan 19, 2023
fde9d57
config option supports 128-bit _generation_, not propagation
dgoffredo Jan 19, 2023
028af2c
exclude _dd.p.tid from extracted W3C tracestate
dgoffredo Jan 19, 2023
02dcf13
remove TraceID::debug()
dgoffredo Jan 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
resource_class: small
steps:
- checkout
- run: find bin/ -executable -type f | xargs shellcheck
- run: find bin/ -executable -type f -print0 | xargs -0 shellcheck

build-bazel:
parameters:
Expand Down
2 changes: 2 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cc_library(
"src/datadog/threaded_event_scheduler.cpp",
"src/datadog/tracer_config.cpp",
"src/datadog/tracer.cpp",
"src/datadog/trace_id.cpp",
"src/datadog/trace_sampler_config.cpp",
"src/datadog/trace_sampler.cpp",
"src/datadog/trace_segment.cpp",
Expand Down Expand Up @@ -101,6 +102,7 @@ cc_library(
"src/datadog/threaded_event_scheduler.h",
"src/datadog/tracer_config.h",
"src/datadog/tracer.h",
"src/datadog/trace_id.h",
"src/datadog/trace_sampler_config.h",
"src/datadog/trace_sampler.h",
"src/datadog/trace_segment.h",
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ target_sources(dd_trace_cpp PRIVATE
src/datadog/threaded_event_scheduler.cpp
src/datadog/tracer_config.cpp
src/datadog/tracer.cpp
src/datadog/trace_id.cpp
src/datadog/trace_sampler_config.cpp
src/datadog/trace_sampler.cpp
src/datadog/trace_segment.cpp
Expand Down Expand Up @@ -176,6 +177,7 @@ target_sources(dd_trace_cpp PUBLIC
src/datadog/threaded_event_scheduler.h
src/datadog/tracer_config.h
src/datadog/tracer.h
src/datadog/trace_id.h
src/datadog/trace_sampler_config.h
src/datadog/trace_sampler.h
src/datadog/trace_segment.h
Expand Down
1 change: 1 addition & 0 deletions bin/check
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ cd "$(dirname "$0")"/..
bin/format --dry-run -Werror
bin/test
bin/bazel-build
find bin/ -executable -type f -print0 | xargs -0 shellcheck
3 changes: 2 additions & 1 deletion src/datadog/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ namespace environment {
MACRO(DD_TRACE_SAMPLING_RULES) \
MACRO(DD_TRACE_STARTUP_LOGS) \
MACRO(DD_TRACE_TAGS_PROPAGATION_MAX_LENGTH) \
MACRO(DD_VERSION)
MACRO(DD_VERSION) \
MACRO(DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)

#define WITH_COMMA(ARG) ARG,

Expand Down
9 changes: 2 additions & 7 deletions src/datadog/extracted_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,17 @@
#include <vector>

#include "optional.h"
#include "trace_id.h"

namespace datadog {
namespace tracing {

struct ExtractedData {
Optional<std::uint64_t> trace_id;
Optional<TraceID> trace_id;
Optional<std::uint64_t> parent_id;
Optional<std::string> origin;
std::vector<std::pair<std::string, std::string>> trace_tags;
Optional<int> sampling_priority;
// If this `ExtractedData` was created on account of `PropagationStyle::W3C`
// and trace context was successfully extracted, then `full_w3c_trace_id_hex`
// contains the hex-encoded 128-bit trace ID. `trace_id` will be the least
// significant 64 bits of the same value. `full_w3c_trace_id_hex` is used for
// the `W3C` injection style.
Optional<std::string> full_w3c_trace_id_hex;
// If this `ExtractedData` was created on account of `PropagationStyle::W3C`,
// then `additional_w3c_tracestate` contains the parts of the "tracestate"
// header that are not the "dd" (Datadog) entry. If there are no other parts,
Expand Down
36 changes: 29 additions & 7 deletions src/datadog/hex.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

// This component provides a function, `hex`, for formatting an integral value
// This component provides functions for formatting an unsigned integral value
// in hexadecimal.

#include <cassert>
Expand All @@ -12,12 +12,14 @@
namespace datadog {
namespace tracing {

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

// 4 bits per hex digit char
char buffer[std::numeric_limits<UnsignedInteger>::digits / 4];

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

// Return the specified unsigned `value` formatted as a lower-case hexadecimal
// string with leading zeroes.
template <typename UnsignedInteger>
std::string hex_padded(UnsignedInteger value) {
static_assert(!std::numeric_limits<UnsignedInteger>::is_signed);

// 4 bits per hex digit char.
char buffer[std::numeric_limits<UnsignedInteger>::digits / 4];

const int base = 16;
auto result =
std::to_chars(std::begin(buffer), std::end(buffer), value, base);
assert(result.ec == std::errc());

const auto num_zeroes = sizeof(buffer) - (result.ptr - std::begin(buffer));
std::string padded(num_zeroes, '0');
padded.append(std::begin(buffer), result.ptr);
return padded;
}

} // namespace tracing
} // namespace datadog
31 changes: 25 additions & 6 deletions src/datadog/id_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace {
extern "C" void on_fork();
#endif

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

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

thread_local DefaultIDGenerator thread_local_generator;
thread_local Uint64Generator thread_local_generator;

#ifndef _MSC_VER
void on_fork() { thread_local_generator.seed_with_random(); }
#endif

} // namespace
class DefaultIDGenerator : public IDGenerator {
const bool trace_id_128_bit_;

public:
explicit DefaultIDGenerator(bool trace_id_128_bit)
: trace_id_128_bit_(trace_id_128_bit) {}

TraceID trace_id() const override {
TraceID result;
result.low = thread_local_generator();
if (trace_id_128_bit_) {
result.high = thread_local_generator();
}
return result;
}

const IDGenerator default_id_generator = []() {
return thread_local_generator();
std::uint64_t span_id() const override { return thread_local_generator(); }
};

} // namespace

std::shared_ptr<const IDGenerator> default_id_generator(bool trace_id_128_bit) {
return std::make_shared<DefaultIDGenerator>(trace_id_128_bit);
}

} // namespace tracing
} // namespace datadog
20 changes: 13 additions & 7 deletions src/datadog/id_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@
// This component provides facilities for generating sequences of IDs used as
// span IDs and trace IDs.
//
// `IDGenerator` is an alias for `std::function<std::uint64_t()>`.
// `IDGenerator` is an interface for generating trace IDs and span IDs.
//
// `default_id_generator` is an `IDGenerator` that produces a thread-local
// pseudo-random sequence of uniformly distributed 63-bit unsigned integers. The
// sequence is randomly seeded one per thread and anytime the process forks.
// The IDs are 63-bit (instead of 64-bit) to ease compatibility with peer
// runtimes that don't have a native 64-bit unsigned numeric type.
// sequence is randomly seeded once per thread and anytime the process forks.

#include <cstdint>
#include <functional>
#include <memory>

#include "trace_id.h"

namespace datadog {
namespace tracing {

using IDGenerator = std::function<std::uint64_t()>;
class IDGenerator {
public:
virtual ~IDGenerator() = default;

virtual std::uint64_t span_id() const = 0;
virtual TraceID trace_id() const = 0;
};

extern const IDGenerator default_id_generator;
std::shared_ptr<const IDGenerator> default_id_generator(bool trace_id_128_bit);

} // namespace tracing
} // namespace datadog
1 change: 0 additions & 1 deletion src/datadog/limiter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <algorithm>
#include <cmath>
#include <iostream>
#include <numeric>

namespace datadog {
Expand Down
10 changes: 10 additions & 0 deletions src/datadog/sampling_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
namespace datadog {
namespace tracing {

// Return a hash value for the specified `value`. `value` is one of the
// following:
//
// - a 64-bit span ID
// - a 64-bit trace ID
// - the lower 64 bits of a 128-bit trace ID
//
// The resulting hash value is compared with an upper bound provided by
// `max_id_from_rate` (below) to determine whether the span/trace associated
// with `value` is eligible for keeping on statistical grounds.
inline std::uint64_t knuth_hash(std::uint64_t value) {
return value * UINT64_C(1111111111111111111);
}
Expand Down
5 changes: 3 additions & 2 deletions src/datadog/span.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ namespace datadog {
namespace tracing {

Span::Span(SpanData* data, const std::shared_ptr<TraceSegment>& trace_segment,
const IDGenerator& generate_span_id, const Clock& clock)
const std::function<std::uint64_t()>& generate_span_id,
const Clock& clock)
: trace_segment_(trace_segment),
data_(data),
generate_span_id_(generate_span_id),
Expand Down Expand Up @@ -62,7 +63,7 @@ void Span::inject(DictWriter& writer) const {

std::uint64_t Span::id() const { return data_->span_id; }

std::uint64_t Span::trace_id() const { return data_->trace_id; }
TraceID Span::trace_id() const { return data_->trace_id; }

Optional<std::uint64_t> Span::parent_id() const {
if (data_->parent_id == 0) {
Expand Down
20 changes: 10 additions & 10 deletions src/datadog/span.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@
// via the `set_end_time` member function prior to the span's destruction.

#include <chrono>
#include <cstdint>
#include <functional>
#include <memory>

#include "clock.h"
#include "error.h"
#include "id_generator.h"
#include "optional.h"
#include "string_view.h"
#include "trace_id.h"

namespace datadog {
namespace tracing {
Expand All @@ -61,19 +62,18 @@ class TraceSegment;
class Span {
std::shared_ptr<TraceSegment> trace_segment_;
SpanData* data_;
IDGenerator generate_span_id_;
std::function<std::uint64_t()> generate_span_id_;
Clock clock_;
Optional<std::chrono::steady_clock::time_point> end_time_;

public:
// Create a span whose properties are stored in the specified `data` and that
// is associated with the specified `trace_segment`. Optionally specify
// `generate_span_id` to generate IDs of child spans, and a `clock` to
// determine start and end times. If `generate_span_id` and `clock` are not
// specified`, then `default_id_generator` and `default_clock` are used
// instead respectively.
// Create a span whose properties are stored in the specified `data`, that is
// associated with the specified `trace_segment`, that uses the specified
// `generate_span_id` to generate IDs of child spans, and that uses the
// specified `clock` to determine start and end times.
Span(SpanData* data, const std::shared_ptr<TraceSegment>& trace_segment,
const IDGenerator& generate_span_id, const Clock& clock);
const std::function<std::uint64_t()>& generate_span_id,
const Clock& clock);
Span(const Span&) = delete;
Span(Span&&) = default;
Span& operator=(Span&&) = default;
Expand All @@ -95,7 +95,7 @@ class Span {
// Return this span's ID (span ID).
std::uint64_t id() const;
// Return the ID of the trace of which this span is a part.
std::uint64_t trace_id() const;
TraceID trace_id() const;
// Return the ID of this span's parent span, or return null if this span has
// no parent.
Optional<std::uint64_t> parent_id() const;
Expand Down
2 changes: 1 addition & 1 deletion src/datadog/span_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Expected<void> msgpack_encode(std::string& destination, const SpanData& span) {
return msgpack::pack_string(destination, span.resource);
},
"trace_id", [&](auto& destination) {
msgpack::pack_integer(destination, span.trace_id);
msgpack::pack_integer(destination, span.trace_id.low);
return Expected<void>{};
},
"span_id", [&](auto& destination) {
Expand Down
3 changes: 2 additions & 1 deletion src/datadog/span_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "expected.h"
#include "optional.h"
#include "string_view.h"
#include "trace_id.h"

namespace datadog {
namespace tracing {
Expand All @@ -24,7 +25,7 @@ struct SpanData {
std::string service_type;
std::string name;
std::string resource;
std::uint64_t trace_id = 0;
TraceID trace_id;
std::uint64_t span_id = 0;
std::uint64_t parent_id = 0;
TimePoint start;
Expand Down
1 change: 1 addition & 0 deletions src/datadog/tags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const std::string span_sampling_mechanism = "_dd.span_sampling.mechanism";
const std::string span_sampling_rule_rate = "_dd.span_sampling.rule_rate";
const std::string span_sampling_limit = "_dd.span_sampling.max_per_second";
const std::string w3c_extraction_error = "_dd.w3c_extraction_error";
const std::string trace_id_high = "_dd.p.tid";

} // namespace internal

Expand Down
1 change: 1 addition & 0 deletions src/datadog/tags.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern const std::string span_sampling_mechanism;
extern const std::string span_sampling_rule_rate;
extern const std::string span_sampling_limit;
extern const std::string w3c_extraction_error;
extern const std::string trace_id_high;
} // namespace internal

// Return whether the specified `tag_name` is reserved for use internal to this
Expand Down
Loading