66
77namespace datadog {
88namespace tracing {
9+ namespace {
10+
11+ using Rules =
12+ std::unordered_map<SpanMatcher, TraceSamplerRate, SpanMatcher::Hash>;
13+
14+ Expected<Rules> parse_trace_sampling_rules (const nlohmann::json& json_rules) {
15+ Rules parsed_rules;
16+
17+ std::string type = json_rules.type_name ();
18+ if (type != " array" ) {
19+ std::string message;
20+ return Error{Error::TRACE_SAMPLING_RULES_WRONG_TYPE, std::move (message)};
21+ }
22+
23+ for (const auto & json_rule : json_rules) {
24+ auto matcher = SpanMatcher::from_json (json_rule);
25+ if (auto * error = matcher.if_error ()) {
26+ std::string prefix;
27+ return error->with_prefix (prefix);
28+ }
29+
30+ TraceSamplerRate rate;
31+ if (auto sample_rate = json_rule.find (" sample_rate" );
32+ sample_rate != json_rule.end ()) {
33+ type = sample_rate->type_name ();
34+ if (type != " number" ) {
35+ std::string message;
36+ return Error{Error::TRACE_SAMPLING_RULES_SAMPLE_RATE_WRONG_TYPE,
37+ std::move (message)};
38+ }
39+
40+ auto maybe_rate = Rate::from (*sample_rate);
41+ if (auto error = maybe_rate.if_error ()) {
42+ return *error;
43+ }
44+
45+ rate.value = *maybe_rate;
46+ }
47+
48+ if (auto provenance_it = json_rule.find (" provenance" );
49+ provenance_it != json_rule.cend ()) {
50+ if (!provenance_it->is_string ()) {
51+ std::string message;
52+ return Error{Error::TRACE_SAMPLING_RULES_SAMPLE_RATE_WRONG_TYPE,
53+ std::move (message)};
54+ }
55+
56+ auto provenance = provenance_it->get <std::string_view>();
57+ if (provenance == " customer" ) {
58+ rate.mechanism = SamplingMechanism::REMOTE_RULE;
59+ } else if (provenance == " dynamic" ) {
60+ rate.mechanism = SamplingMechanism::REMOTE_ADAPTIVE_RULE;
61+ }
62+ }
63+
64+ parsed_rules.emplace (std::move (*matcher), std::move (rate));
65+ }
66+
67+ return parsed_rules;
68+ }
69+
70+ } // namespace
971
1072ConfigManager::ConfigManager (const FinalizedTracerConfig& config)
1173 : clock_(config.clock),
1274 default_metadata_ (config.metadata),
1375 trace_sampler_(
1476 std::make_shared<TraceSampler>(config.trace_sampler, clock_)),
77+ rules_(config.trace_sampler.rules),
1578 span_defaults_(std::make_shared<SpanDefaults>(config.defaults)),
1679 report_traces_(config.report_traces) {}
1780
1881std::shared_ptr<TraceSampler> ConfigManager::trace_sampler () {
1982 std::lock_guard<std::mutex> lock (mutex_);
20- return trace_sampler_. value () ;
83+ return trace_sampler_;
2184}
2285
2386std::shared_ptr<const SpanDefaults> ConfigManager::span_defaults () {
@@ -35,32 +98,48 @@ std::vector<ConfigMetadata> ConfigManager::update(const ConfigUpdate& conf) {
3598
3699 std::lock_guard<std::mutex> lock (mutex_);
37100
101+ decltype (rules_) rules;
102+
38103 if (!conf.trace_sampling_rate ) {
39- reset_config (ConfigName::TRACE_SAMPLING_RATE, trace_sampler_, metadata);
104+ auto found = default_metadata_.find (ConfigName::TRACE_SAMPLING_RATE);
105+ if (found != default_metadata_.cend ()) {
106+ metadata.push_back (found->second );
107+ }
40108 } else {
41109 ConfigMetadata trace_sampling_metadata (
42110 ConfigName::TRACE_SAMPLING_RATE,
43111 to_string (*conf.trace_sampling_rate , 1 ),
44112 ConfigMetadata::Origin::REMOTE_CONFIG);
45113
46- TraceSamplerConfig trace_sampler_cfg;
47- trace_sampler_cfg.sample_rate = *conf.trace_sampling_rate ;
114+ auto rate = Rate::from (*conf.trace_sampling_rate );
115+ rules[catch_all] = TraceSamplerRate{*rate, SamplingMechanism::RULE};
116+
117+ metadata.emplace_back (std::move (trace_sampling_metadata));
118+ }
48119
49- auto finalized_trace_sampler_cfg = finalize_config (trace_sampler_cfg);
50- if (auto error = finalized_trace_sampler_cfg.if_error ()) {
51- trace_sampling_metadata.error = *error;
120+ if (!conf.trace_sampling_rules ) {
121+ auto found = default_metadata_.find (ConfigName::TRACE_SAMPLING_RULES);
122+ if (found != default_metadata_.cend ()) {
123+ metadata.emplace_back (found->second );
52124 }
125+ } else {
126+ ConfigMetadata trace_sampling_rules_metadata (
127+ ConfigName::TRACE_SAMPLING_RULES, conf.trace_sampling_rules ->dump (),
128+ ConfigMetadata::Origin::REMOTE_CONFIG);
53129
54- auto trace_sampler =
55- std::make_shared<TraceSampler>(*finalized_trace_sampler_cfg, clock_);
130+ auto maybe_rules = parse_trace_sampling_rules (*conf.trace_sampling_rules );
131+ if (auto error = maybe_rules.if_error ()) {
132+ trace_sampling_rules_metadata.error = std::move (*error);
133+ } else {
134+ rules.merge (*maybe_rules);
135+ }
56136
57- // This reset rate limiting and `TraceSampler` has no `operator==`.
58- // TODO: Instead of creating another `TraceSampler`, we should
59- // update the default sampling rate.
60- trace_sampler_ = std::move (trace_sampler);
61- metadata.emplace_back (std::move (trace_sampling_metadata));
137+ metadata.emplace_back (std::move (trace_sampling_rules_metadata));
62138 }
63139
140+ rules.insert (rules_.cbegin (), rules_.cend ());
141+ trace_sampler_->set_rules (rules);
142+
64143 if (!conf.tags ) {
65144 reset_config (ConfigName::TAGS, span_defaults_, metadata);
66145 } else {
@@ -109,10 +188,9 @@ std::vector<ConfigMetadata> ConfigManager::reset() { return update({}); }
109188
110189nlohmann::json ConfigManager::config_json () const {
111190 std::lock_guard<std::mutex> lock (mutex_);
112- return nlohmann::json{
113- {" defaults" , to_json (*span_defaults_.value ())},
114- {" trace_sampler" , trace_sampler_.value ()->config_json ()},
115- {" report_traces" , report_traces_.value ()}};
191+ return nlohmann::json{{" defaults" , to_json (*span_defaults_.value ())},
192+ {" trace_sampler" , trace_sampler_->config_json ()},
193+ {" report_traces" , report_traces_.value ()}};
116194}
117195
118196} // namespace tracing
0 commit comments