Skip to content

Commit 9f1d409

Browse files
committed
collect all config sources in tracer_config in a map
1 parent 4ec5ab4 commit 9f1d409

File tree

3 files changed

+143
-84
lines changed

3 files changed

+143
-84
lines changed

include/datadog/config.h

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#pragma once
22

3+
#include <string>
4+
#include <type_traits>
5+
#include <unordered_map>
6+
#include <utility>
7+
#include <vector>
8+
39
#include "error.h"
410
#include "optional.h"
511

@@ -56,14 +62,72 @@ struct ConfigMetadata {
5662
: name(n), value(std::move(v)), origin(orig), error(std::move(err)) {}
5763
};
5864

65+
// Return the chosen configuration value, in order of precedence: `from_env`,
66+
// `from_user`, and `fallback`.
67+
// This overload directly populates both telemetry_configs[config_name] and
68+
// metadata[config_name] using the stringified value, with all values found,
69+
// from lowest to highest precedence. Returns the chosen value directly.
70+
//
71+
// The fallback parameter is optional and defaults to nullptr.
72+
template <typename Value, typename Stringifier = std::nullptr_t,
73+
typename DefaultValue = std::nullptr_t>
74+
Value pick(const Optional<Value>& from_env, const Optional<Value>& from_user,
75+
std::unordered_map<ConfigName, std::vector<ConfigMetadata>>*
76+
telemetry_configs,
77+
std::unordered_map<ConfigName, ConfigMetadata>* metadata,
78+
ConfigName config_name, DefaultValue fallback = nullptr,
79+
Stringifier to_string_fn = nullptr) {
80+
auto stringify = [&](const Value& v) -> std::string {
81+
if constexpr (!std::is_same_v<Stringifier, std::nullptr_t>) {
82+
return to_string_fn(v); // use provided function
83+
} else if constexpr (std::is_constructible_v<std::string, Value>) {
84+
return std::string(v); // default behaviour (works for string-like types)
85+
} else {
86+
static_assert(!std::is_same_v<Value, Value>,
87+
"Non-string types require a stringifier function");
88+
return ""; // unreachable
89+
}
90+
};
91+
92+
std::vector<ConfigMetadata> telemetry_entries;
93+
Optional<Value> chosen_value;
94+
95+
auto add_entry = [&](ConfigMetadata::Origin origin, const Value& val) {
96+
std::string val_str = stringify(val);
97+
telemetry_entries.emplace_back(
98+
ConfigMetadata{config_name, val_str, origin});
99+
chosen_value = val;
100+
};
101+
102+
// Add DEFAULT entry if fallback was provided (detected by type)
103+
if constexpr (!std::is_same_v<DefaultValue, std::nullptr_t>) {
104+
add_entry(ConfigMetadata::Origin::DEFAULT, fallback);
105+
}
106+
107+
if (from_user) {
108+
add_entry(ConfigMetadata::Origin::CODE, *from_user);
109+
}
110+
111+
if (from_env) {
112+
add_entry(ConfigMetadata::Origin::ENVIRONMENT_VARIABLE, *from_env);
113+
}
114+
115+
(*telemetry_configs)[config_name] = std::move(telemetry_entries);
116+
if (!(*telemetry_configs)[config_name].empty()) {
117+
(*metadata)[config_name] = (*telemetry_configs)[config_name].back();
118+
}
119+
120+
return chosen_value.value_or(Value{});
121+
}
122+
59123
// Return a pair containing the configuration origin and value of a
60124
// configuration value chosen from one of the specified `from_env`,
61125
// `from_config`, and `fallback`. This function defines the relative precedence
62126
// among configuration values originating from the environment, programmatic
63127
// configuration, and default configuration.
64128
template <typename Value, typename DefaultValue>
65-
std::pair<ConfigMetadata::Origin, Value> pick(const Optional<Value> &from_env,
66-
const Optional<Value> &from_user,
129+
std::pair<ConfigMetadata::Origin, Value> pick(const Optional<Value>& from_env,
130+
const Optional<Value>& from_user,
67131
DefaultValue fallback) {
68132
if (from_env) {
69133
return {ConfigMetadata::Origin::ENVIRONMENT_VARIABLE, *from_env};

include/datadog/telemetry/product.h

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

66
#include <string>
77
#include <unordered_map>
8+
#include <vector>
89

910
namespace datadog::telemetry {
1011

@@ -30,7 +31,7 @@ struct Product final {
3031
/// Optional error message related to the product status.
3132
tracing::Optional<std::string> error_message;
3233
/// Map of configuration settings for the product.
33-
std::unordered_map<tracing::ConfigName, tracing::ConfigMetadata>
34+
std::unordered_map<tracing::ConfigName, std::vector<tracing::ConfigMetadata>>
3435
configurations;
3536
};
3637

src/datadog/tracer_config.cpp

Lines changed: 75 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
#include <unordered_map>
99
#include <vector>
1010

11+
#include "datadog/optional.h"
1112
#include "datadog_agent.h"
1213
#include "json.hpp"
1314
#include "null_logger.h"
1415
#include "parse_util.h"
1516
#include "platform_util.h"
1617
#include "string_util.h"
17-
#include "tags.h"
1818
#include "threaded_event_scheduler.h"
1919

2020
namespace datadog {
@@ -284,81 +284,81 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &user_config,
284284
final_config.clock = clock;
285285
final_config.logger = logger;
286286

287-
ConfigMetadata::Origin origin;
287+
std::unordered_map<ConfigName, std::vector<ConfigMetadata>>
288+
all_sources_configs;
288289

289-
std::tie(origin, final_config.defaults.service) =
290-
pick(env_config->service, user_config.service, "");
291-
292-
if (final_config.defaults.service.empty()) {
293-
final_config.defaults.service = get_process_name();
294-
}
295-
296-
final_config.metadata[ConfigName::SERVICE_NAME] = ConfigMetadata(
297-
ConfigName::SERVICE_NAME, final_config.defaults.service, origin);
290+
// DD_SERVICE
291+
final_config.defaults.service = pick(
292+
env_config->service, user_config.service, &all_sources_configs,
293+
&final_config.metadata, ConfigName::SERVICE_NAME, get_process_name());
298294

295+
// Service type
299296
final_config.defaults.service_type =
300297
value_or(env_config->service_type, user_config.service_type, "web");
301298

302299
// DD_ENV
303-
std::tie(origin, final_config.defaults.environment) =
304-
pick(env_config->environment, user_config.environment, "");
305-
final_config.metadata[ConfigName::SERVICE_ENV] = ConfigMetadata(
306-
ConfigName::SERVICE_ENV, final_config.defaults.environment, origin);
300+
final_config.defaults.environment = pick(
301+
env_config->environment, user_config.environment, &all_sources_configs,
302+
&final_config.metadata, ConfigName::SERVICE_ENV);
307303

308304
// DD_VERSION
309-
std::tie(origin, final_config.defaults.version) =
310-
pick(env_config->version, user_config.version, "");
311-
final_config.metadata[ConfigName::SERVICE_VERSION] = ConfigMetadata(
312-
ConfigName::SERVICE_VERSION, final_config.defaults.version, origin);
305+
final_config.defaults.version =
306+
pick(env_config->version, user_config.version, &all_sources_configs,
307+
&final_config.metadata, ConfigName::SERVICE_VERSION);
313308

309+
// Span name
314310
final_config.defaults.name = value_or(env_config->name, user_config.name, "");
315311

316312
// DD_TAGS
317-
std::tie(origin, final_config.defaults.tags) =
318-
pick(env_config->tags, user_config.tags,
319-
std::unordered_map<std::string, std::string>{});
320-
final_config.metadata[ConfigName::TAGS] = ConfigMetadata(
321-
ConfigName::TAGS, join_tags(final_config.defaults.tags), origin);
313+
final_config.defaults.tags =
314+
pick(env_config->tags, user_config.tags, &all_sources_configs,
315+
&final_config.metadata, ConfigName::TAGS,
316+
std::unordered_map<std::string, std::string>{},
317+
[](const auto &tags) { return join_tags(tags); });
322318

323319
// Extraction Styles
324320
const std::vector<PropagationStyle> default_propagation_styles{
325321
PropagationStyle::DATADOG, PropagationStyle::W3C,
326322
PropagationStyle::BAGGAGE};
327323

328-
std::tie(origin, final_config.extraction_styles) =
324+
final_config.extraction_styles =
329325
pick(env_config->extraction_styles, user_config.extraction_styles,
330-
default_propagation_styles);
326+
&all_sources_configs, &final_config.metadata,
327+
ConfigName::EXTRACTION_STYLES, default_propagation_styles,
328+
[](const std::vector<PropagationStyle> &styles) {
329+
return join_propagation_styles(styles);
330+
});
331+
331332
if (final_config.extraction_styles.empty()) {
332333
return Error{Error::MISSING_SPAN_EXTRACTION_STYLE,
333334
"At least one extraction style must be specified."};
334335
}
335-
final_config.metadata[ConfigName::EXTRACTION_STYLES] = ConfigMetadata(
336-
ConfigName::EXTRACTION_STYLES,
337-
join_propagation_styles(final_config.extraction_styles), origin);
338336

339337
// Injection Styles
340-
std::tie(origin, final_config.injection_styles) =
338+
final_config.injection_styles =
341339
pick(env_config->injection_styles, user_config.injection_styles,
342-
default_propagation_styles);
340+
&all_sources_configs, &final_config.metadata,
341+
ConfigName::INJECTION_STYLES, default_propagation_styles,
342+
[](const std::vector<PropagationStyle> &styles) {
343+
return join_propagation_styles(styles);
344+
});
345+
343346
if (final_config.injection_styles.empty()) {
344347
return Error{Error::MISSING_SPAN_INJECTION_STYLE,
345348
"At least one injection style must be specified."};
346349
}
347-
final_config.metadata[ConfigName::INJECTION_STYLES] = ConfigMetadata(
348-
ConfigName::INJECTION_STYLES,
349-
join_propagation_styles(final_config.injection_styles), origin);
350350

351351
// Startup Logs
352-
std::tie(origin, final_config.log_on_startup) =
353-
pick(env_config->log_on_startup, user_config.log_on_startup, true);
354-
final_config.metadata[ConfigName::STARTUP_LOGS] = ConfigMetadata(
355-
ConfigName::STARTUP_LOGS, to_string(final_config.log_on_startup), origin);
352+
final_config.log_on_startup = pick(
353+
env_config->log_on_startup, user_config.log_on_startup,
354+
&all_sources_configs, &final_config.metadata, ConfigName::STARTUP_LOGS,
355+
true, [](const bool &b) { return to_string(b); });
356356

357357
// Report traces
358-
std::tie(origin, final_config.report_traces) =
359-
pick(env_config->report_traces, user_config.report_traces, true);
360-
final_config.metadata[ConfigName::REPORT_TRACES] = ConfigMetadata(
361-
ConfigName::REPORT_TRACES, to_string(final_config.report_traces), origin);
358+
final_config.report_traces = pick(
359+
env_config->report_traces, user_config.report_traces,
360+
&all_sources_configs, &final_config.metadata, ConfigName::REPORT_TRACES,
361+
true, [](const bool &b) { return to_string(b); });
362362

363363
// Report hostname
364364
final_config.report_hostname =
@@ -369,12 +369,11 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &user_config,
369369
env_config->max_tags_header_size, user_config.max_tags_header_size, 512);
370370

371371
// 128b Trace IDs
372-
std::tie(origin, final_config.generate_128bit_trace_ids) =
372+
final_config.generate_128bit_trace_ids =
373373
pick(env_config->generate_128bit_trace_ids,
374-
user_config.generate_128bit_trace_ids, true);
375-
final_config.metadata[ConfigName::GENEREATE_128BIT_TRACE_IDS] =
376-
ConfigMetadata(ConfigName::GENEREATE_128BIT_TRACE_IDS,
377-
to_string(final_config.generate_128bit_trace_ids), origin);
374+
user_config.generate_128bit_trace_ids, &all_sources_configs,
375+
&final_config.metadata, ConfigName::GENEREATE_128BIT_TRACE_IDS, true,
376+
[](const bool &b) { return to_string(b); });
378377

379378
// Integration name & version
380379
final_config.integration_name = value_or(
@@ -383,18 +382,19 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &user_config,
383382
value_or(env_config->integration_version, user_config.integration_version,
384383
tracer_version);
385384

386-
// Baggage
387-
std::tie(origin, final_config.baggage_opts.max_items) =
388-
pick(env_config->baggage_max_items, user_config.baggage_max_items, 64);
389-
final_config.metadata[ConfigName::TRACE_BAGGAGE_MAX_ITEMS] = ConfigMetadata(
390-
ConfigName::TRACE_BAGGAGE_MAX_ITEMS,
391-
std::to_string(final_config.baggage_opts.max_items), origin);
392-
393-
std::tie(origin, final_config.baggage_opts.max_bytes) =
394-
pick(env_config->baggage_max_bytes, user_config.baggage_max_bytes, 8192);
395-
final_config.metadata[ConfigName::TRACE_BAGGAGE_MAX_BYTES] = ConfigMetadata(
396-
ConfigName::TRACE_BAGGAGE_MAX_BYTES,
397-
std::to_string(final_config.baggage_opts.max_bytes), origin);
385+
// Baggage - max items
386+
final_config.baggage_opts.max_items =
387+
pick(env_config->baggage_max_items, user_config.baggage_max_items,
388+
&all_sources_configs, &final_config.metadata,
389+
ConfigName::TRACE_BAGGAGE_MAX_ITEMS, 64UL,
390+
[](const size_t &i) { return std::to_string(i); });
391+
392+
// Baggage - max bytes
393+
final_config.baggage_opts.max_bytes =
394+
pick(env_config->baggage_max_bytes, user_config.baggage_max_bytes,
395+
&all_sources_configs, &final_config.metadata,
396+
ConfigName::TRACE_BAGGAGE_MAX_BYTES, 8192UL,
397+
[](const size_t &i) { return std::to_string(i); });
398398

399399
if (final_config.baggage_opts.max_items <= 0 ||
400400
final_config.baggage_opts.max_bytes < 3) {
@@ -453,39 +453,33 @@ Expected<FinalizedTracerConfig> finalize_config(const TracerConfig &user_config,
453453
final_config.telemetry = std::move(*telemetry_final_config);
454454
final_config.telemetry.products.emplace_back(telemetry::Product{
455455
telemetry::Product::Name::tracing, true, tracer_version, nullopt,
456-
nullopt, final_config.metadata});
456+
nullopt, all_sources_configs});
457457
} else {
458458
return std::move(telemetry_final_config.error());
459459
}
460460

461461
// APM Tracing Enabled
462-
std::tie(origin, final_config.tracing_enabled) =
463-
pick(env_config->tracing_enabled, user_config.tracing_enabled, true);
464-
final_config.metadata[ConfigName::APM_TRACING_ENABLED] =
465-
ConfigMetadata(ConfigName::APM_TRACING_ENABLED,
466-
to_string(final_config.tracing_enabled), origin);
462+
final_config.tracing_enabled =
463+
pick(env_config->tracing_enabled, user_config.tracing_enabled,
464+
&all_sources_configs, &final_config.metadata,
465+
ConfigName::APM_TRACING_ENABLED, true,
466+
[](const bool &b) { return to_string(b); });
467467

468468
{
469469
// Resource Renaming Enabled
470-
bool resource_renaming_enabled;
471-
std::tie(origin, resource_renaming_enabled) =
472-
pick(env_config->resource_renaming_enabled,
473-
user_config.resource_renaming_enabled, false);
474-
475-
final_config.metadata[ConfigName::TRACE_RESOURCE_RENAMING_ENABLED] =
476-
ConfigMetadata(ConfigName::TRACE_RESOURCE_RENAMING_ENABLED,
477-
to_string(resource_renaming_enabled), origin);
470+
const bool resource_renaming_enabled = pick(
471+
env_config->resource_renaming_enabled,
472+
user_config.resource_renaming_enabled, &all_sources_configs,
473+
&final_config.metadata, ConfigName::TRACE_RESOURCE_RENAMING_ENABLED,
474+
false, [](const bool &b) { return to_string(b); });
478475

479476
// Resource Renaming Always Simplified Endpoint
480-
bool resource_renaming_always_simplified_endpoint;
481-
std::tie(origin, resource_renaming_always_simplified_endpoint) =
477+
const bool resource_renaming_always_simplified_endpoint =
482478
pick(env_config->resource_renaming_always_simplified_endpoint,
483-
user_config.resource_renaming_always_simplified_endpoint, false);
484-
final_config.metadata
485-
[ConfigName::TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT] =
486-
ConfigMetadata(
487-
ConfigName::TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT,
488-
to_string(resource_renaming_always_simplified_endpoint), origin);
479+
user_config.resource_renaming_always_simplified_endpoint,
480+
&all_sources_configs, &final_config.metadata,
481+
ConfigName::TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT,
482+
false, [](const bool &b) { return to_string(b); });
489483

490484
if (!resource_renaming_enabled) {
491485
final_config.resource_renaming_mode =

0 commit comments

Comments
 (0)