Skip to content

Commit 6dacac2

Browse files
authored
feat: support DD_TRACE_ENABLED dynamic configuration (#96)
1 parent 8c3969c commit 6dacac2

File tree

10 files changed

+104
-38
lines changed

10 files changed

+104
-38
lines changed

src/datadog/config_manager.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,25 @@ ConfigManager::ConfigManager(const FinalizedTracerConfig& config)
1111
std::make_shared<TraceSampler>(config.trace_sampler, clock_)),
1212
current_trace_sampler_(default_trace_sampler_),
1313
default_span_defaults_(std::make_shared<SpanDefaults>(config.defaults)),
14-
current_span_defaults_(default_span_defaults_) {}
14+
current_span_defaults_(default_span_defaults_),
15+
default_report_traces_(config.report_traces),
16+
current_report_traces_(default_report_traces_) {}
1517

16-
std::shared_ptr<TraceSampler> ConfigManager::get_trace_sampler() {
18+
std::shared_ptr<TraceSampler> ConfigManager::trace_sampler() {
1719
std::lock_guard<std::mutex> lock(mutex_);
1820
return current_trace_sampler_;
1921
}
2022

21-
std::shared_ptr<const SpanDefaults> ConfigManager::get_span_defaults() {
23+
std::shared_ptr<const SpanDefaults> ConfigManager::span_defaults() {
2224
std::lock_guard<std::mutex> lock(mutex_);
2325
return current_span_defaults_;
2426
}
2527

28+
bool ConfigManager::report_traces() {
29+
std::lock_guard<std::mutex> lock(mutex_);
30+
return current_report_traces_;
31+
}
32+
2633
void ConfigManager::update(const ConfigUpdate& conf) {
2734
std::lock_guard<std::mutex> lock(mutex_);
2835

@@ -47,19 +54,27 @@ void ConfigManager::update(const ConfigUpdate& conf) {
4754
} else {
4855
current_span_defaults_ = default_span_defaults_;
4956
}
57+
58+
if (conf.report_traces) {
59+
current_report_traces_ = *conf.report_traces;
60+
} else {
61+
current_report_traces_ = default_report_traces_;
62+
}
5063
}
5164

5265
void ConfigManager::reset() {
5366
std::lock_guard<std::mutex> lock(mutex_);
5467
current_trace_sampler_ = default_trace_sampler_;
5568
current_span_defaults_ = default_span_defaults_;
69+
current_report_traces_ = default_report_traces_;
5670
}
5771

5872
nlohmann::json ConfigManager::config_json() const {
5973
std::lock_guard<std::mutex> lock(mutex_);
6074
return nlohmann::json{
6175
{"default", to_json(*current_span_defaults_)},
62-
{"trace_sampler", current_trace_sampler_->config_json()}};
76+
{"trace_sampler", current_trace_sampler_->config_json()},
77+
{"report_traces", current_report_traces_}};
6378
}
6479

6580
} // namespace tracing

src/datadog/config_manager.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,20 @@ class ConfigManager {
2525
std::shared_ptr<const SpanDefaults> default_span_defaults_;
2626
std::shared_ptr<const SpanDefaults> current_span_defaults_;
2727

28+
bool default_report_traces_;
29+
bool current_report_traces_;
30+
2831
public:
2932
ConfigManager(const FinalizedTracerConfig& config);
3033

3134
// Return the `TraceSampler` consistent with the most recent configuration.
32-
std::shared_ptr<TraceSampler> get_trace_sampler();
35+
std::shared_ptr<TraceSampler> trace_sampler();
3336

3437
// Return the `SpanDefaults` consistent with the most recent configuration.
35-
std::shared_ptr<const SpanDefaults> get_span_defaults();
38+
std::shared_ptr<const SpanDefaults> span_defaults();
39+
40+
// Return whether traces should be sent to the collector.
41+
bool report_traces();
3642

3743
// Apply the specified `conf` update.
3844
void update(const ConfigUpdate& conf);

src/datadog/config_update.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ namespace tracing {
1414
// Configurations can be `nullopt` to signal the absence of a value from the
1515
// remote configuration value.
1616
struct ConfigUpdate {
17+
Optional<bool> report_traces;
1718
Optional<TraceSamplerConfig> trace_sampler;
1819
Optional<std::unordered_map<std::string, std::string>> tags;
1920
};

src/datadog/remote_config.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ namespace {
2929
// within the array.
3030
enum CapabilitiesFlag : uint64_t {
3131
APM_TRACING_SAMPLE_RATE = 1 << 12,
32-
APM_TRACING_TAGS = 1 << 15
32+
APM_TRACING_TAGS = 1 << 15,
33+
APM_TRACING_ENABLED = 1 << 19
3334
};
3435

3536
constexpr std::array<uint8_t, sizeof(uint64_t)> capabilities_byte_array(
@@ -44,7 +45,8 @@ constexpr std::array<uint8_t, sizeof(uint64_t)> capabilities_byte_array(
4445
}
4546

4647
constexpr std::array<uint8_t, sizeof(uint64_t)> k_apm_capabilities =
47-
capabilities_byte_array(APM_TRACING_SAMPLE_RATE | APM_TRACING_TAGS);
48+
capabilities_byte_array(APM_TRACING_SAMPLE_RATE | APM_TRACING_TAGS |
49+
APM_TRACING_ENABLED);
4850

4951
constexpr StringView k_apm_product = "APM_TRACING";
5052
constexpr StringView k_apm_product_path_substring = "/APM_TRACING/";
@@ -94,6 +96,15 @@ ConfigUpdate parse_dynamic_config(const nlohmann::json& j) {
9496
}
9597
}
9698

99+
if (auto tracing_enabled_it = j.find("tracing_enabled");
100+
tracing_enabled_it != j.cend()) {
101+
if (tracing_enabled_it->is_boolean()) {
102+
config_update.report_traces = tracing_enabled_it->get<bool>();
103+
} else {
104+
// TODO: report to telemetry
105+
}
106+
}
107+
97108
return config_update;
98109
}
99110

src/datadog/trace_segment.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ TraceSegment::TraceSegment(
107107
const std::shared_ptr<TraceSampler>& trace_sampler,
108108
const std::shared_ptr<SpanSampler>& span_sampler,
109109
const std::shared_ptr<const SpanDefaults>& defaults,
110+
const std::shared_ptr<ConfigManager>& config_manager,
110111
const RuntimeID& runtime_id, bool sampling_delegation_enabled,
111112
bool sampling_decision_was_delegated_to_me,
112113
const std::vector<PropagationStyle>& injection_styles,
@@ -133,13 +134,15 @@ TraceSegment::TraceSegment(
133134
sampling_decision_(std::move(sampling_decision)),
134135
additional_w3c_tracestate_(std::move(additional_w3c_tracestate)),
135136
additional_datadog_w3c_tracestate_(
136-
std::move(additional_datadog_w3c_tracestate)) {
137+
std::move(additional_datadog_w3c_tracestate)),
138+
config_manager_(config_manager) {
137139
assert(logger_);
138140
assert(collector_);
139141
assert(tracer_telemetry_);
140142
assert(trace_sampler_);
141143
assert(span_sampler_);
142144
assert(defaults_);
145+
assert(config_manager_);
143146

144147
sampling_delegation_.enabled = sampling_delegation_enabled;
145148
sampling_delegation_.decision_was_delegated_to_me =
@@ -264,10 +267,12 @@ void TraceSegment::span_finished() {
264267
span.tags[tags::internal::runtime_id] = runtime_id_.string();
265268
}
266269

267-
const auto result = collector_->send(std::move(spans_), trace_sampler_);
268-
if (auto* error = result.if_error()) {
269-
logger_->log_error(
270-
error->with_prefix("Error sending spans to collector: "));
270+
if (config_manager_->report_traces()) {
271+
const auto result = collector_->send(std::move(spans_), trace_sampler_);
272+
if (auto* error = result.if_error()) {
273+
logger_->log_error(
274+
error->with_prefix("Error sending spans to collector: "));
275+
}
271276
}
272277

273278
tracer_telemetry_->metrics().tracer.trace_segments_closed.inc();

src/datadog/trace_segment.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <utility>
3333
#include <vector>
3434

35+
#include "config_manager.h"
3536
#include "expected.h"
3637
#include "metrics.h"
3738
#include "optional.h"
@@ -74,6 +75,9 @@ class TraceSegment {
7475
Optional<SamplingDecision> sampling_decision_;
7576
Optional<std::string> additional_w3c_tracestate_;
7677
Optional<std::string> additional_datadog_w3c_tracestate_;
78+
79+
std::shared_ptr<ConfigManager> config_manager_;
80+
7781
// See `doc/sampling-delegation.md` for more information about
7882
// `struct SamplingDelegation`.
7983
struct SamplingDelegation {
@@ -100,6 +104,7 @@ class TraceSegment {
100104
const std::shared_ptr<TraceSampler>& trace_sampler,
101105
const std::shared_ptr<SpanSampler>& span_sampler,
102106
const std::shared_ptr<const SpanDefaults>& defaults,
107+
const std::shared_ptr<ConfigManager>& config_manager,
103108
const RuntimeID& runtime_id, bool sampling_delegation_enabled,
104109
bool sampling_decision_was_delegated_to_me,
105110
const std::vector<PropagationStyle>& injection_styles,

src/datadog/tracer.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ nlohmann::json Tracer::config_json() const {
104104
Span Tracer::create_span() { return create_span(SpanConfig{}); }
105105

106106
Span Tracer::create_span(const SpanConfig& config) {
107-
auto defaults = config_manager_->get_span_defaults();
107+
auto defaults = config_manager_->span_defaults();
108108
auto span_data = std::make_unique<SpanData>();
109109
span_data->apply_config(*defaults, config, clock_);
110110
span_data->trace_id = generator_->trace_id(span_data->start);
@@ -120,9 +120,9 @@ Span Tracer::create_span(const SpanConfig& config) {
120120
const auto span_data_ptr = span_data.get();
121121
tracer_telemetry_->metrics().tracer.trace_segments_created_new.inc();
122122
const auto segment = std::make_shared<TraceSegment>(
123-
logger_, collector_, tracer_telemetry_,
124-
config_manager_->get_trace_sampler(), span_sampler_, defaults,
125-
runtime_id_, sampling_delegation_enabled_,
123+
logger_, collector_, tracer_telemetry_, config_manager_->trace_sampler(),
124+
span_sampler_, defaults, config_manager_, runtime_id_,
125+
sampling_delegation_enabled_,
126126
false /* sampling_decision_was_delegated_to_me */, injection_styles_,
127127
hostname_, nullopt /* origin */, tags_header_max_size_,
128128
std::move(trace_tags), nullopt /* sampling_decision */,
@@ -240,8 +240,7 @@ Expected<Span> Tracer::extract_span(const DictReader& reader,
240240

241241
// We're done extracting fields. Now create the span.
242242
// This is similar to what we do in `create_span`.
243-
span_data->apply_config(*config_manager_->get_span_defaults(), config,
244-
clock_);
243+
span_data->apply_config(*config_manager_->span_defaults(), config, clock_);
245244
span_data->span_id = generator_->span_id();
246245
span_data->trace_id = *trace_id;
247246
span_data->parent_id = *parent_id;
@@ -292,10 +291,9 @@ Expected<Span> Tracer::extract_span(const DictReader& reader,
292291
const auto span_data_ptr = span_data.get();
293292
tracer_telemetry_->metrics().tracer.trace_segments_created_continued.inc();
294293
const auto segment = std::make_shared<TraceSegment>(
295-
logger_, collector_, tracer_telemetry_,
296-
config_manager_->get_trace_sampler(), span_sampler_,
297-
config_manager_->get_span_defaults(), runtime_id_,
298-
sampling_delegation_enabled_, delegate_sampling_decision,
294+
logger_, collector_, tracer_telemetry_, config_manager_->trace_sampler(),
295+
span_sampler_, config_manager_->span_defaults(), config_manager_,
296+
runtime_id_, sampling_delegation_enabled_, delegate_sampling_decision,
299297
injection_styles_, hostname_, std::move(origin), tags_header_max_size_,
300298
std::move(trace_tags), std::move(sampling_decision),
301299
std::move(additional_w3c_tracestate),

src/datadog/tracer_config.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "datadog_agent.h"
1313
#include "environment.h"
1414
#include "json.hpp"
15-
#include "null_collector.h"
1615
#include "parse_util.h"
1716
#include "string_view.h"
1817

@@ -312,14 +311,12 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &config,
312311
result.log_on_startup = !falsy(*startup_env);
313312
}
314313

315-
bool report_traces = config.report_traces;
314+
result.report_traces = config.report_traces;
316315
if (auto enabled_env = lookup(environment::DD_TRACE_ENABLED)) {
317-
report_traces = !falsy(*enabled_env);
316+
result.report_traces = !falsy(*enabled_env);
318317
}
319318

320-
if (!report_traces) {
321-
result.collector = std::make_shared<NullCollector>();
322-
} else if (!config.collector) {
319+
if (!config.collector) {
323320
auto finalized = finalize_config(config.agent, result.logger, clock);
324321
if (auto *error = finalized.if_error()) {
325322
return std::move(*error);

src/datadog/tracer_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class FinalizedTracerConfig {
166166
std::string integration_name;
167167
std::string integration_version;
168168
bool delegate_trace_sampling;
169+
bool report_traces;
169170
};
170171

171172
// Return a `FinalizedTracerConfig` from the specified `config` and from any

test/test_remote_config.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ REMOTE_CONFIG_TEST("response processing") {
6363
config.defaults.service = "testsvc";
6464
config.defaults.environment = "test";
6565
config.trace_sampler.sample_rate = 1.0;
66+
config.report_traces = true;
6667
const auto config_manager =
6768
std::make_shared<ConfigManager>(*finalize_config(config));
6869

@@ -160,13 +161,31 @@ REMOTE_CONFIG_TEST("response processing") {
160161

161162
SECTION("valid remote configuration") {
162163
// clang-format off
164+
// {
165+
// "lib_config": {
166+
// "library_language": "all",
167+
// "library_version": "latest",
168+
// "service_name": "testsvc",
169+
// "env": "test",
170+
// "tracing_enabled": false,
171+
// "tracing_sampling_rate": 0.6,
172+
// "tracing_tags": [
173+
// "hello:world",
174+
// "foo:bar"
175+
// ]
176+
// },
177+
// "service_target": {
178+
// "service": "testsvc",
179+
// "env": "test"
180+
// }
181+
// }
163182
const std::string json_input = R"({
164183
"targets": "ewogICAgInNpZ25lZCI6IHsKICAgICAgICAiY3VzdG9tIjogewogICAgICAgICAgICAiYWdlbnRfcmVmcmVzaF9pbnRlcnZhbCI6IDUsCiAgICAgICAgICAgICJvcGFxdWVfYmFja2VuZF9zdGF0ZSI6ICJleUoyWlhKemFXOXVJam95TENKemRHRjBaU0k2ZXlKbWFXeGxYMmhoYzJobGN5STZleUprWVhSaFpHOW5MekV3TURBeE1qVTROREF2UVZCTlgxUlNRVU5KVGtjdk9ESTNaV0ZqWmpoa1ltTXpZV0l4TkRNMFpETXlNV05pT0RGa1ptSm1OMkZtWlRZMU5HRTBZall4TVRGalpqRTJOakJpTnpGalkyWTRPVGM0TVRrek9DOHlPVEE0Tm1Ka1ltVTFNRFpsTmpoaU5UQm1NekExTlRneU0yRXpaR0UxWTJVd05USTRaakUyTkRCa05USmpaamc0TmpFNE1UWmhZV0U1Wm1ObFlXWTBJanBiSW05WVpESnBlVU16ZUM5b1JXc3hlWFZoWTFoR04xbHFjWEpwVGs5QldVdHVaekZ0V0UwMU5WWktUSGM5SWwxOWZYMD0iCiAgICAgICAgfSwKICAgICAgICAic3BlY192ZXJzaW9uIjogIjEuMC4wIiwKICAgICAgICAidGFyZ2V0cyI6IHsKICAgICAgICAgICAgImZvby9BUE1fVFJBQ0lORy8zMCI6IHsKICAgICAgICAgICAgICAgICJoYXNoZXMiOiB7CiAgICAgICAgICAgICAgICAgICAgInNoYTI1NiI6ICJhMTc3NzY4YjIwYjdjN2Y4NDQ5MzVjYWU2OWM1YzVlZDg4ZWFhZTIzNGUwMTgyYTc4MzU5OTczMzllNTUyNGJjIgogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICJsZW5ndGgiOiAzNzQKICAgICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgInZlcnNpb24iOiA2NjIwNDMyMAogICAgfQp9",
165184
"client_configs": ["foo/APM_TRACING/30"],
166185
"target_files": [
167186
{
168187
"path": "foo/APM_TRACING/30",
169-
"raw": "eyAiaWQiOiAiODI3ZWFjZjhkYmMzYWIxNDM0ZDMyMWNiODFkZmJmN2FmZTY1NGE0YjYxMTFjZjE2NjBiNzFjY2Y4OTc4MTkzOCIsICJyZXZpc2lvbiI6IDE2OTgxNjcxMjYwNjQsICJzY2hlbWFfdmVyc2lvbiI6ICJ2MS4wLjAiLCAiYWN0aW9uIjogImVuYWJsZSIsICJsaWJfY29uZmlnIjogeyAibGlicmFyeV9sYW5ndWFnZSI6ICJhbGwiLCAibGlicmFyeV92ZXJzaW9uIjogImxhdGVzdCIsICJzZXJ2aWNlX25hbWUiOiAidGVzdHN2YyIsICJlbnYiOiAidGVzdCIsICJ0cmFjaW5nX2VuYWJsZWQiOiB0cnVlLCAidHJhY2luZ19zYW1wbGluZ19yYXRlIjogMC42LCAidHJhY2luZ190YWdzIjogWyJoZWxsbzp3b3JsZCIsICJmb286YmFyIl0gfSwgInNlcnZpY2VfdGFyZ2V0IjogeyAic2VydmljZSI6ICJ0ZXN0c3ZjIiwgImVudiI6ICJ0ZXN0IiB9IH0="
188+
"raw": "eyAiaWQiOiAiODI3ZWFjZjhkYmMzYWIxNDM0ZDMyMWNiODFkZmJmN2FmZTY1NGE0YjYxMTFjZjE2NjBiNzFjY2Y4OTc4MTkzOCIsICJyZXZpc2lvbiI6IDE2OTgxNjcxMjYwNjQsICJzY2hlbWFfdmVyc2lvbiI6ICJ2MS4wLjAiLCAiYWN0aW9uIjogImVuYWJsZSIsICJsaWJfY29uZmlnIjogeyAibGlicmFyeV9sYW5ndWFnZSI6ICJhbGwiLCAibGlicmFyeV92ZXJzaW9uIjogImxhdGVzdCIsICJzZXJ2aWNlX25hbWUiOiAidGVzdHN2YyIsICJlbnYiOiAidGVzdCIsICJ0cmFjaW5nX2VuYWJsZWQiOiBmYWxzZSwgInRyYWNpbmdfc2FtcGxpbmdfcmF0ZSI6IDAuNiwgInRyYWNpbmdfdGFncyI6IFsiaGVsbG86d29ybGQiLCAiZm9vOmJhciJdIH0sICJzZXJ2aWNlX3RhcmdldCI6IHsgInNlcnZpY2UiOiAidGVzdHN2YyIsICJlbnYiOiAidGVzdCIgfSB9"
170189
}
171190
]
172191
})";
@@ -179,14 +198,17 @@ REMOTE_CONFIG_TEST("response processing") {
179198

180199
REQUIRE(!response_json.is_discarded());
181200

182-
const auto old_trace_sampler = config_manager->get_trace_sampler();
183-
const auto old_span_defaults = config_manager->get_span_defaults();
201+
const auto old_trace_sampler = config_manager->trace_sampler();
202+
const auto old_span_defaults = config_manager->span_defaults();
203+
const auto old_report_traces = config_manager->report_traces();
184204
rc.process_response(response_json);
185-
const auto new_trace_sampler = config_manager->get_trace_sampler();
186-
const auto new_span_defaults = config_manager->get_span_defaults();
205+
const auto new_trace_sampler = config_manager->trace_sampler();
206+
const auto new_span_defaults = config_manager->span_defaults();
207+
const auto new_report_traces = config_manager->report_traces();
187208

188209
CHECK(new_trace_sampler != old_trace_sampler);
189210
CHECK(new_span_defaults != old_span_defaults);
211+
CHECK(new_report_traces != old_report_traces);
190212

191213
SECTION("reset confguration") {
192214
SECTION(
@@ -206,8 +228,13 @@ REMOTE_CONFIG_TEST("response processing") {
206228
REQUIRE(!response_json.is_discarded());
207229

208230
rc.process_response(response_json);
209-
const auto current_trace_sampler = config_manager->get_trace_sampler();
231+
const auto current_trace_sampler = config_manager->trace_sampler();
232+
const auto current_span_defaults = config_manager->span_defaults();
233+
const auto current_report_traces = config_manager->report_traces();
234+
210235
CHECK(old_trace_sampler == current_trace_sampler);
236+
CHECK(old_span_defaults == current_span_defaults);
237+
CHECK(old_report_traces == current_report_traces);
211238
}
212239

213240
SECTION("missing configuration field -> field should be reset") {
@@ -232,7 +259,7 @@ REMOTE_CONFIG_TEST("response processing") {
232259
REQUIRE(!response_json.is_discarded());
233260

234261
rc.process_response(response_json);
235-
const auto current_trace_sampler = config_manager->get_trace_sampler();
262+
const auto current_trace_sampler = config_manager->trace_sampler();
236263
CHECK(old_trace_sampler == current_trace_sampler);
237264
}
238265
}
@@ -275,9 +302,9 @@ REMOTE_CONFIG_TEST("response processing") {
275302

276303
REQUIRE(!response_json.is_discarded());
277304

278-
const auto old_sampling_rate = config_manager->get_trace_sampler();
305+
const auto old_sampling_rate = config_manager->trace_sampler();
279306
rc.process_response(response_json);
280-
const auto new_sampling_rate = config_manager->get_trace_sampler();
307+
const auto new_sampling_rate = config_manager->trace_sampler();
281308

282309
CHECK(new_sampling_rate == old_sampling_rate);
283310
}

0 commit comments

Comments
 (0)