Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ cc_library(
"src/datadog/span_matcher.cpp",
"src/datadog/span_sampler_config.cpp",
"src/datadog/span_sampler.cpp",
"src/datadog/string_util.cpp",
"src/datadog/tag_propagation.cpp",
"src/datadog/tags.cpp",
"src/datadog/threaded_event_scheduler.cpp",
Expand All @@ -51,6 +52,7 @@ cc_library(
hdrs = [
"src/datadog/base64.h",
"src/datadog/cerr_logger.h",
"src/datadog/config.h",
"src/datadog/clock.h",
"src/datadog/config_manager.h",
"src/datadog/config_update.h",
Expand Down Expand Up @@ -99,6 +101,7 @@ cc_library(
"src/datadog/span_matcher.h",
"src/datadog/span_sampler_config.h",
"src/datadog/span_sampler.h",
"src/datadog/string_util.h",
"src/datadog/string_view.h",
"src/datadog/tag_propagation.h",
"src/datadog/tags.h",
Expand Down
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ target_sources(dd_trace_cpp-objects PRIVATE
src/datadog/span_matcher.cpp
src/datadog/span_sampler_config.cpp
src/datadog/span_sampler.cpp
src/datadog/string_util.cpp
src/datadog/tags.cpp
src/datadog/tag_propagation.cpp
src/datadog/threaded_event_scheduler.cpp
Expand All @@ -142,6 +143,7 @@ target_sources(dd_trace_cpp-objects PUBLIC
BASE_DIRS src/
FILES
src/datadog/base64.h
src/datadog/config.h
src/datadog/cerr_logger.h
src/datadog/clock.h
src/datadog/config_manager.h
Expand Down Expand Up @@ -191,6 +193,7 @@ target_sources(dd_trace_cpp-objects PUBLIC
src/datadog/span_matcher.h
src/datadog/span_sampler_config.h
src/datadog/span_sampler.h
src/datadog/string_util.h
src/datadog/string_view.h
src/datadog/tag_propagation.h
src/datadog/tags.h
Expand Down
72 changes: 72 additions & 0 deletions src/datadog/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once

#include "error.h"
#include "optional.h"

namespace datadog {
namespace tracing {

// Enumerates available configuration names for the tracing library
enum class ConfigName : char {
SERVICE_NAME,
SERVICE_ENV,
SERVICE_VERSION,
REPORT_TRACES,
TAGS,
EXTRACTION_STYLES,
INJECTION_STYLES,
STARTUP_LOGS,
REPORT_TELEMETRY,
DELEGATE_SAMPLING,
GENEREATE_128BIT_TRACE_IDS,
AGENT_URL,
RC_POLL_INTERVAL,
TRACE_SAMPLING_RATE,
TRACE_SAMPLING_LIMIT,
TRACE_SAMPLING_RULES,
SPAN_SAMPLING_RULES,
};

// Represents metadata for configuration parameters
struct ConfigMetadata {
enum class Origin : char {
ENVIRONMENT_VARIABLE, // Originating from environment variables
CODE, // Defined in code
REMOTE_CONFIG, // Retrieeved from remote configuration
DEFAULT // Default value
};

// Name of the configuration parameter
ConfigName name;
// Value of the configuration parameter
std::string value;
// Origin of the configuration parameter
Origin origin;
// Optional error associated with the configuration parameter
Optional<Error> error;

ConfigMetadata() = default;
ConfigMetadata(ConfigName n, std::string v, Origin orig,
Optional<Error> err = nullopt)
: name(n), value(std::move(v)), origin(orig), error(err) {}
};

// Return a pair containing the configuration origin and value of a
// configuration value chosen from one of the specified `from_env`,
// `from_config`, and `fallback`. This function defines the relative precedence
// among configuration values originating from the environment, programmatic
// configuration, and default configuration.
template <typename Value, typename DefaultValue>
std::pair<ConfigMetadata::Origin, Value> pick(const Optional<Value> &from_env,
const Optional<Value> &from_user,
DefaultValue fallback) {
if (from_env) {
return {ConfigMetadata::Origin::ENVIRONMENT_VARIABLE, *from_env};
} else if (from_user) {
return {ConfigMetadata::Origin::CODE, *from_user};
}
return {ConfigMetadata::Origin::DEFAULT, fallback};
}

} // namespace tracing
} // namespace datadog
114 changes: 77 additions & 37 deletions src/datadog/config_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,80 +1,120 @@
#include "config_manager.h"

#include <sstream>

#include "parse_util.h"
#include "string_util.h"
#include "trace_sampler.h"

namespace datadog {
namespace tracing {

ConfigManager::ConfigManager(const FinalizedTracerConfig& config)
: clock_(config.clock),
default_trace_sampler_(
default_metadata_(config.metadata),
trace_sampler_(
std::make_shared<TraceSampler>(config.trace_sampler, clock_)),
current_trace_sampler_(default_trace_sampler_),
default_span_defaults_(std::make_shared<SpanDefaults>(config.defaults)),
current_span_defaults_(default_span_defaults_),
default_report_traces_(config.report_traces),
current_report_traces_(default_report_traces_) {}
span_defaults_(std::make_shared<SpanDefaults>(config.defaults)),
report_traces_(config.report_traces) {}

std::shared_ptr<TraceSampler> ConfigManager::trace_sampler() {
std::lock_guard<std::mutex> lock(mutex_);
return current_trace_sampler_;
return trace_sampler_.value();
}

std::shared_ptr<const SpanDefaults> ConfigManager::span_defaults() {
std::lock_guard<std::mutex> lock(mutex_);
return current_span_defaults_;
return span_defaults_.value();
}

bool ConfigManager::report_traces() {
std::lock_guard<std::mutex> lock(mutex_);
return current_report_traces_;
return report_traces_.value();
}

void ConfigManager::update(const ConfigUpdate& conf) {
std::vector<ConfigMetadata> ConfigManager::update(const ConfigUpdate& conf) {
std::vector<ConfigMetadata> metadata;

std::lock_guard<std::mutex> lock(mutex_);

if (conf.trace_sampler) {
if (auto finalized_trace_sampler_cfg =
finalize_config(*conf.trace_sampler)) {
current_trace_sampler_ =
std::make_shared<TraceSampler>(*finalized_trace_sampler_cfg, clock_);
} else {
// TODO: report error
}
if (!conf.trace_sampling_rate) {
reset_config(ConfigName::TRACE_SAMPLING_RATE, trace_sampler_, metadata);
} else {
current_trace_sampler_ = default_trace_sampler_;
}
ConfigMetadata trace_sampling_metadata(
ConfigName::TRACE_SAMPLING_RATE,
to_string(*conf.trace_sampling_rate, 1),
ConfigMetadata::Origin::REMOTE_CONFIG);

TraceSamplerConfig trace_sampler_cfg;
trace_sampler_cfg.sample_rate = *conf.trace_sampling_rate;

if (conf.tags) {
auto new_span_defaults =
std::make_shared<SpanDefaults>(*current_span_defaults_);
new_span_defaults->tags = std::move(*conf.tags);
auto finalized_trace_sampler_cfg = finalize_config(trace_sampler_cfg);
if (auto error = finalized_trace_sampler_cfg.if_error()) {
trace_sampling_metadata.error = *error;
}

auto trace_sampler =
std::make_shared<TraceSampler>(*finalized_trace_sampler_cfg, clock_);

current_span_defaults_ = new_span_defaults;
// This reset rate limiting and `TraceSampler` has no `operator==`.
// TODO: Instead of creating another `TraceSampler`, we should
// update the default sampling rate.
trace_sampler_ = std::move(trace_sampler);
metadata.emplace_back(std::move(trace_sampling_metadata));
}

if (!conf.tags) {
reset_config(ConfigName::TAGS, span_defaults_, metadata);
} else {
current_span_defaults_ = default_span_defaults_;
ConfigMetadata tags_metadata(ConfigName::TAGS, join(*conf.tags, ","),
ConfigMetadata::Origin::REMOTE_CONFIG);

auto parsed_tags = parse_tags(*conf.tags);
if (auto error = parsed_tags.if_error()) {
tags_metadata.error = *error;
}

if (*parsed_tags != span_defaults_.value()->tags) {
auto new_span_defaults =
std::make_shared<SpanDefaults>(*span_defaults_.value());
new_span_defaults->tags = std::move(*parsed_tags);

span_defaults_ = new_span_defaults;
metadata.emplace_back(std::move(tags_metadata));
}
}

if (conf.report_traces) {
current_report_traces_ = *conf.report_traces;
if (!conf.report_traces) {
reset_config(ConfigName::REPORT_TRACES, report_traces_, metadata);
} else {
current_report_traces_ = default_report_traces_;
if (conf.report_traces != report_traces_.value()) {
report_traces_ = *conf.report_traces;
metadata.emplace_back(ConfigName::REPORT_TRACES,
to_string(*conf.report_traces),
ConfigMetadata::Origin::REMOTE_CONFIG);
}
}

return metadata;
}

void ConfigManager::reset() {
std::lock_guard<std::mutex> lock(mutex_);
current_trace_sampler_ = default_trace_sampler_;
current_span_defaults_ = default_span_defaults_;
current_report_traces_ = default_report_traces_;
template <typename T>
void ConfigManager::reset_config(ConfigName name, T& conf,
std::vector<ConfigMetadata>& metadata) {
if (conf.is_original_value()) return;

conf.reset();
metadata.emplace_back(default_metadata_[name]);
}

std::vector<ConfigMetadata> ConfigManager::reset() { return update({}); }

nlohmann::json ConfigManager::config_json() const {
std::lock_guard<std::mutex> lock(mutex_);
return nlohmann::json{
{"default", to_json(*current_span_defaults_)},
{"trace_sampler", current_trace_sampler_->config_json()},
{"report_traces", current_report_traces_}};
{"default", to_json(*span_defaults_.value())},
{"trace_sampler", trace_sampler_.value()->config_json()},
{"report_traces", report_traces_.value()}};
}

} // namespace tracing
Expand Down
51 changes: 43 additions & 8 deletions src/datadog/config_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,58 @@
#include "clock.h"
#include "config_update.h"
#include "json.hpp"
#include "optional.h"
#include "span_defaults.h"
#include "tracer_config.h"

namespace datadog {
namespace tracing {

class ConfigManager {
// A class template for managing dynamic configuration values.
//
// This class allows storing and managing dynamic configuration values. It
// maintains an original value and a current value, allowing for updates and
// resets.
//
// Additionally, it provides methods for accessing the current value and
// checking whether it has been modified from its original state.
template <typename Value>
class DynamicConfig {
Value original_value_;
Optional<Value> current_value_;

public:
// Constructs a DynamicConf object with the given initial value
explicit DynamicConfig(Value original_value)
: original_value_(original_value) {}

// Resets the current value of the configuration to the original value
void reset() { current_value_ = nullopt; }

// Returns whether the current value is the original value
bool is_original_value() const { return !current_value_.has_value(); }

const Value& value() const {
return current_value_.has_value() ? *current_value_ : original_value_;
}

// Updates the current value of the configuration
void operator=(const Value& rhs) { current_value_ = rhs; }
};

mutable std::mutex mutex_;
Clock clock_;
std::shared_ptr<TraceSampler> default_trace_sampler_;
std::shared_ptr<TraceSampler> current_trace_sampler_;
std::unordered_map<ConfigName, ConfigMetadata> default_metadata_;

std::shared_ptr<const SpanDefaults> default_span_defaults_;
std::shared_ptr<const SpanDefaults> current_span_defaults_;
DynamicConfig<std::shared_ptr<TraceSampler>> trace_sampler_;
DynamicConfig<std::shared_ptr<const SpanDefaults>> span_defaults_;
DynamicConfig<bool> report_traces_;

bool default_report_traces_;
bool current_report_traces_;
private:
template <typename T>
void reset_config(ConfigName name, T& conf,
std::vector<ConfigMetadata>& metadata);

public:
ConfigManager(const FinalizedTracerConfig& config);
Expand All @@ -41,11 +76,11 @@ class ConfigManager {
bool report_traces();

// Apply the specified `conf` update.
void update(const ConfigUpdate& conf);
std::vector<ConfigMetadata> update(const ConfigUpdate& conf);

// Restore the configuration that was passed to this object's constructor,
// overriding any previous calls to `update`.
void reset();
std::vector<ConfigMetadata> reset();

// Return a JSON representation of the current configuration managed by this
// object.
Expand Down
4 changes: 2 additions & 2 deletions src/datadog/config_update.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ namespace tracing {
// remote configuration value.
struct ConfigUpdate {
Optional<bool> report_traces;
Optional<TraceSamplerConfig> trace_sampler;
Optional<std::unordered_map<std::string, std::string>> tags;
Optional<double> trace_sampling_rate;
Optional<std::vector<StringView>> tags;
};

} // namespace tracing
Expand Down
Loading