diff --git a/mod_datadog/src/common_conf.cpp b/mod_datadog/src/common_conf.cpp index d2a56a53..7a7f326b 100644 --- a/mod_datadog/src/common_conf.cpp +++ b/mod_datadog/src/common_conf.cpp @@ -15,10 +15,15 @@ void* merge_dir_conf(apr_pool_t* pool, void* base, void* add) { void* final_ptr = init_dir_conf(pool, nullptr); auto conf = static_cast(final_ptr); - conf->tracing_enabled = child->tracing_enabled || parent->tracing_enabled; - - conf->trust_inbound_span = - child->trust_inbound_span || parent->trust_inbound_span; + // Tri-state merge: an explicit directive in the child scope wins over + // whatever the parent had (including the default). Only fall back to the + // parent when the child never set the directive. + conf->tracing_enabled = + child->tracing_enabled ? child->tracing_enabled : parent->tracing_enabled; + + conf->trust_inbound_span = child->trust_inbound_span + ? child->trust_inbound_span + : parent->trust_inbound_span; conf->tags = child->tags; auto tmp = parent->tags; diff --git a/mod_datadog/src/common_conf.h b/mod_datadog/src/common_conf.h index 23bd4638..a8e5368a 100644 --- a/mod_datadog/src/common_conf.h +++ b/mod_datadog/src/common_conf.h @@ -2,6 +2,7 @@ #include +#include #include #include @@ -18,8 +19,11 @@ struct Module final { }; struct Directory final { - bool tracing_enabled = true; - bool trust_inbound_span = true; + // `std::nullopt` means "inherit from the enclosing scope"; any concrete + // value (true/false) was set explicitly via a directive and wins over the + // parent during merge. The effective default at read sites is `true`. + std::optional tracing_enabled; + std::optional trust_inbound_span; std::unordered_map tags; // RUM diff --git a/mod_datadog/src/tracing/hooks.cpp b/mod_datadog/src/tracing/hooks.cpp index f84d185b..b6df5f07 100644 --- a/mod_datadog/src/tracing/hooks.cpp +++ b/mod_datadog/src/tracing/hooks.cpp @@ -101,9 +101,11 @@ int on_fixups(request_rec* r, Tracer& g_tracer, module* datadog_module) { // subrequests/internal redirection? request_rec* main_r = r->prev ? r->prev : r->main; - auto* dir_conf = static_cast( + auto* dir_conf = static_cast( ap_get_module_config(main_r->per_dir_config, datadog_module)); - if (dir_conf == nullptr || !dir_conf->tracing_enabled) return DECLINED; + if (dir_conf == nullptr || !dir_conf->tracing_enabled.value_or(true)) { + return DECLINED; + } void* data = ap_get_module_config(main_r->request_config, datadog_module); if (!data) return DECLINED; @@ -116,7 +118,9 @@ int on_fixups(request_rec* r, Tracer& g_tracer, module* datadog_module) { // Trace request auto* dir_conf = static_cast( ap_get_module_config(r->per_dir_config, datadog_module)); - if (dir_conf == nullptr || !dir_conf->tracing_enabled) return DECLINED; + if (dir_conf == nullptr || !dir_conf->tracing_enabled.value_or(true)) { + return DECLINED; + } void* data = ap_get_module_config(r->request_config, datadog_module); if (data) @@ -127,7 +131,7 @@ int on_fixups(request_rec* r, Tracer& g_tracer, module* datadog_module) { // In case we fail to use the inbound span, then, start a new trace // ¯\_(ツ)_/¯ There is nothing we can do about it. - if (dir_conf->trust_inbound_span) { + if (dir_conf->trust_inbound_span.value_or(true)) { auto extracted_span = g_tracer.extract_span(utils::HeaderReader(r->headers_in), options); if (auto error = extracted_span.if_error()) {