Skip to content

Commit 32d2d5b

Browse files
bm1549claude
andcommitted
refactor: apply review feedback — move rules parser, simplify helpers, catch specifics
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8f89c38 commit 32d2d5b

8 files changed

Lines changed: 220 additions & 185 deletions

File tree

WORKSPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ http_archive(
4040
urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.2.14/rules_cc-0.2.14.tar.gz"],
4141
)
4242

43+
# This pulls the upstream yaml-cpp 0.8.0 tarball directly.
44+
# MODULE.bazel uses "0.8.0.bcr.1" because that is the BCR (Bazel Central
45+
# Registry) patched release; the underlying library version is the same 0.8.0.
4346
http_archive(
4447
name = "yaml_cpp",
4548
sha256 = "fbe74bbdcee21d656715688706da3c8becfd946d92cd44705cc6098bb23b3a16",

include/datadog/config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ struct ConfigMetadata {
6464
: name(n), value(std::move(v)), origin(orig), error(std::move(err)) {}
6565
};
6666

67+
// 3-parameter overload (env, user, default) kept for backward compatibility
68+
// with external projects (e.g., nginx-datadog, httpd-datadog) that include
69+
// this public header. New internal code should prefer the 5-parameter
70+
// overload that also accepts fleet and local stable config sources.
71+
//
6772
// Returns the final configuration value using the following
6873
// precedence order: environment > user code > default, and populates metadata:
6974
// `metadata`: Records ALL configuration sources that were provided,

include/datadog/trace_sampler_config.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
namespace datadog {
2121
namespace tracing {
2222

23+
class Logger;
2324
struct StableConfigs;
2425

2526
struct TraceSamplerRule final {
@@ -44,7 +45,8 @@ struct TraceSamplerConfig {
4445

4546
class FinalizedTraceSamplerConfig {
4647
friend Expected<FinalizedTraceSamplerConfig> finalize_config(
47-
const TraceSamplerConfig& config, const StableConfigs* stable_configs);
48+
const TraceSamplerConfig& config, const StableConfigs* stable_configs,
49+
Logger* logger);
4850
friend class FinalizedTracerConfig;
4951

5052
FinalizedTraceSamplerConfig() = default;
@@ -61,7 +63,7 @@ class FinalizedTraceSamplerConfig {
6163

6264
Expected<FinalizedTraceSamplerConfig> finalize_config(
6365
const TraceSamplerConfig& config,
64-
const StableConfigs* stable_configs = nullptr);
66+
const StableConfigs* stable_configs = nullptr, Logger* logger = nullptr);
6567

6668
} // namespace tracing
6769
} // namespace datadog

src/datadog/span_sampler_config.cpp

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,55 @@ namespace datadog {
1515
namespace tracing {
1616
namespace {
1717

18+
// Parse a stable config JSON string as an array of sampling rules.
19+
// `customize_rule` is a callable that receives (Rule&, const json_rule&) to set
20+
// rule-specific fields beyond the base matcher and sample_rate.
21+
// Returns nullopt on any parse error (stable config errors are non-fatal).
22+
template <typename Rule, typename Json, typename Customize>
23+
Optional<std::vector<Rule>> parse_stable_config_rules(
24+
const StableConfig &cfg, const std::string &key, Logger &logger,
25+
Customize customize_rule) {
26+
auto val = cfg.lookup(key);
27+
if (!val || val->empty()) return nullopt;
28+
29+
try {
30+
auto json_rules = Json::parse(*val);
31+
if (!json_rules.is_array()) {
32+
logger.log_error([&key](std::ostream &log) {
33+
log << "Unable to parse JSON sampling rules from " << key
34+
<< ": expected a JSON array";
35+
});
36+
return nullopt;
37+
}
38+
39+
std::vector<Rule> rules;
40+
for (const auto &json_rule : json_rules) {
41+
auto matcher = from_json(json_rule);
42+
if (matcher.if_error()) {
43+
logger.log_error([&key](std::ostream &log) {
44+
log << "Unable to parse JSON sampling rules from " << key
45+
<< ": invalid rule matcher";
46+
});
47+
return nullopt;
48+
}
49+
50+
Rule rule{*matcher};
51+
if (auto sr = json_rule.find("sample_rate");
52+
sr != json_rule.end() && sr->is_number()) {
53+
rule.sample_rate = *sr;
54+
}
55+
customize_rule(rule, json_rule);
56+
rules.emplace_back(std::move(rule));
57+
}
58+
return rules;
59+
} catch (...) {
60+
logger.log_error([&key](std::ostream &log) {
61+
log << "Unable to parse JSON sampling rules from " << key;
62+
});
63+
return nullopt;
64+
}
65+
}
66+
1867
std::string to_string(const std::vector<SpanSamplerConfig::Rule> &rules) {
1968
nlohmann::json res;
2069
for (const auto &r : rules) {
@@ -242,10 +291,10 @@ Expected<FinalizedSpanSamplerConfig> finalize_config(
242291
Optional<std::vector<SpanSamplerConfig::Rule>> fleet_rules;
243292
Optional<std::vector<SpanSamplerConfig::Rule>> local_rules;
244293
if (stable_configs) {
245-
auto parse_span_rules = [](const StableConfig &cfg,
246-
const std::string &key) {
294+
auto parse_span_rules = [&logger](const StableConfig &cfg,
295+
const std::string &key) {
247296
return parse_stable_config_rules<SpanSamplerConfig::Rule, nlohmann::json>(
248-
cfg, key,
297+
cfg, key, logger,
249298
[](SpanSamplerConfig::Rule &rule, const nlohmann::json &json_rule) {
250299
if (auto mps = json_rule.find("max_per_second");
251300
mps != json_rule.end() && mps->is_number()) {

src/datadog/stable_config.h

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717

1818
#include <string>
1919
#include <unordered_map>
20-
#include <vector>
21-
22-
#include "json_serializer.h"
2320

2421
namespace datadog {
2522
namespace tracing {
@@ -55,38 +52,5 @@ struct StableConfigs {
5552
// Returns empty configs (no error) if files don't exist.
5653
StableConfigs load_stable_configs(Logger& logger);
5754

58-
// Parse a stable config JSON string as an array of sampling rules.
59-
// `customize_rule` is a callable that receives (Rule&, const json_rule&) to set
60-
// rule-specific fields beyond the base matcher and sample_rate.
61-
// Returns nullopt on any parse error (stable config errors are non-fatal).
62-
template <typename Rule, typename Json, typename Customize>
63-
Optional<std::vector<Rule>> parse_stable_config_rules(
64-
const StableConfig& cfg, const std::string& key, Customize customize_rule) {
65-
auto val = cfg.lookup(key);
66-
if (!val || val->empty()) return nullopt;
67-
68-
try {
69-
auto json_rules = Json::parse(*val);
70-
if (!json_rules.is_array()) return nullopt;
71-
72-
std::vector<Rule> rules;
73-
for (const auto& json_rule : json_rules) {
74-
auto matcher = from_json(json_rule);
75-
if (matcher.if_error()) return nullopt;
76-
77-
Rule rule{*matcher};
78-
if (auto sr = json_rule.find("sample_rate");
79-
sr != json_rule.end() && sr->is_number()) {
80-
rule.sample_rate = *sr;
81-
}
82-
customize_rule(rule, json_rule);
83-
rules.emplace_back(std::move(rule));
84-
}
85-
return rules;
86-
} catch (...) {
87-
return nullopt;
88-
}
89-
}
90-
9155
} // namespace tracing
9256
} // namespace datadog

src/datadog/trace_sampler_config.cpp

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <datadog/environment.h>
2+
#include <datadog/logger.h>
23
#include <datadog/trace_sampler_config.h>
34
#include <datadog/trace_source.h>
45

@@ -7,6 +8,7 @@
78

89
#include "json.hpp"
910
#include "json_serializer.h"
11+
#include "null_logger.h"
1012
#include "parse_util.h"
1113
#include "stable_config.h"
1214
#include "string_util.h"
@@ -156,20 +158,74 @@ Optional<double> stable_config_double(const StableConfig &cfg,
156158
return *result;
157159
}
158160

161+
// Parse a stable config JSON string as an array of sampling rules.
162+
// `customize_rule` is a callable that receives (Rule&, const json_rule&) to set
163+
// rule-specific fields beyond the base matcher and sample_rate.
164+
// Returns nullopt on any parse error (stable config errors are non-fatal).
165+
template <typename Rule, typename Json, typename Customize>
166+
Optional<std::vector<Rule>> parse_stable_config_rules(
167+
const StableConfig &cfg, const std::string &key, Logger &logger,
168+
Customize customize_rule) {
169+
auto val = cfg.lookup(key);
170+
if (!val || val->empty()) return nullopt;
171+
172+
try {
173+
auto json_rules = Json::parse(*val);
174+
if (!json_rules.is_array()) {
175+
logger.log_error([&key](std::ostream &log) {
176+
log << "Unable to parse JSON sampling rules from " << key
177+
<< ": expected a JSON array";
178+
});
179+
return nullopt;
180+
}
181+
182+
std::vector<Rule> rules;
183+
for (const auto &json_rule : json_rules) {
184+
auto matcher = from_json(json_rule);
185+
if (matcher.if_error()) {
186+
logger.log_error([&key](std::ostream &log) {
187+
log << "Unable to parse JSON sampling rules from " << key
188+
<< ": invalid rule matcher";
189+
});
190+
return nullopt;
191+
}
192+
193+
Rule rule{*matcher};
194+
if (auto sr = json_rule.find("sample_rate");
195+
sr != json_rule.end() && sr->is_number()) {
196+
rule.sample_rate = *sr;
197+
}
198+
customize_rule(rule, json_rule);
199+
rules.emplace_back(std::move(rule));
200+
}
201+
return rules;
202+
} catch (...) {
203+
logger.log_error([&key](std::ostream &log) {
204+
log << "Unable to parse JSON sampling rules from " << key;
205+
});
206+
return nullopt;
207+
}
208+
}
209+
159210
// Try to parse a stable config string value as trace sampling rules JSON.
160-
// Returns empty vector on any parse error (stable config errors are non-fatal).
211+
// Returns nullopt on any parse error (stable config errors are non-fatal).
161212
Optional<std::vector<TraceSamplerConfig::Rule>> stable_config_sampling_rules(
162-
const StableConfig &cfg, const std::string &key) {
213+
const StableConfig &cfg, const std::string &key, Logger &logger) {
163214
return parse_stable_config_rules<TraceSamplerConfig::Rule, nlohmann::json>(
164-
cfg, key, [](TraceSamplerConfig::Rule &, const nlohmann::json &) {});
215+
cfg, key, logger,
216+
[](TraceSamplerConfig::Rule &, const nlohmann::json &) {});
165217
}
166218

167219
} // namespace
168220

169221
TraceSamplerConfig::Rule::Rule(const SpanMatcher &base) : SpanMatcher(base) {}
170222

171223
Expected<FinalizedTraceSamplerConfig> finalize_config(
172-
const TraceSamplerConfig &config, const StableConfigs *stable_configs) {
224+
const TraceSamplerConfig &config, const StableConfigs *stable_configs,
225+
Logger *logger) {
226+
NullLogger null_logger;
227+
Logger &log = logger ? *logger : static_cast<Logger &>(null_logger);
228+
173229
Expected<TraceSamplerConfig> env_config = load_trace_sampler_env_config();
174230
if (auto error = env_config.if_error()) {
175231
return *error;
@@ -184,9 +240,9 @@ Expected<FinalizedTraceSamplerConfig> finalize_config(
184240
Optional<std::vector<TraceSamplerConfig::Rule>> local_rules;
185241
if (stable_configs) {
186242
fleet_rules = stable_config_sampling_rules(stable_configs->fleet,
187-
"DD_TRACE_SAMPLING_RULES");
243+
"DD_TRACE_SAMPLING_RULES", log);
188244
local_rules = stable_config_sampling_rules(stable_configs->local,
189-
"DD_TRACE_SAMPLING_RULES");
245+
"DD_TRACE_SAMPLING_RULES", log);
190246
}
191247

192248
if (fleet_rules) {

0 commit comments

Comments
 (0)