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
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions components-rs/agent_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub unsafe extern "C" fn ddog_apply_agent_info(
info.filter_tags_regex.as_ref().and_then(|f| f.require.as_deref()).unwrap_or(&[]).to_owned(),
info.filter_tags_regex.as_ref().and_then(|f| f.reject.as_deref()).unwrap_or(&[]).to_owned(),
info.ignore_resources.as_deref().unwrap_or(&[]).to_owned(),
info.client_drop_p0s.unwrap_or(false),
info.version.as_deref(),
);
}
}
Expand Down Expand Up @@ -87,6 +89,8 @@ pub unsafe extern "C" fn ddog_apply_agent_info_concentrator_config(
info.filter_tags_regex.as_ref().and_then(|f| f.require.as_deref()).unwrap_or(&[]).to_owned(),
info.filter_tags_regex.as_ref().and_then(|f| f.reject.as_deref()).unwrap_or(&[]).to_owned(),
info.ignore_resources.as_deref().unwrap_or(&[]).to_owned(),
info.client_drop_p0s.unwrap_or(false),
info.version.as_deref(),
);
}
}
7 changes: 7 additions & 0 deletions components-rs/ddtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,13 @@ bool ddog_exception_hash_limiter_inc(struct ddog_SidecarTransport *connection,
*/
bool ddog_is_agent_info_ready(void);

/**
* Returns true when the agent supports client-side stats computation:
* agent info has been received, `client_drop_p0s` is true, and the reported
* agent version is >= 7.65.0.
*/
bool ddog_agent_has_stats_computation(void);

/**
* Look up (or lazily create) the concentrator for `(env, version, service)` and invoke
* `callback` with a shared reference to it while holding the global read lock.
Expand Down
28 changes: 27 additions & 1 deletion components-rs/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub struct PhpSpanStats<'a> {
}

#[inline]
fn char_slice_str(s: CharSlice) -> &str {
fn char_slice_str(s: CharSlice<'_>) -> &str {
s.try_to_utf8().unwrap_or("")
}

Expand Down Expand Up @@ -232,6 +232,19 @@ static SPAN_CONCENTRATORS: LazyLock<RwLock<HashMap<String, SpanConcentrator>>> =
/// i.e. the sidecar has received and applied the agent's /info response.
static AGENT_INFO_RECEIVED: AtomicBool = AtomicBool::new(false);

/// Set to true once agent info confirms `client_drop_p0s` is true and the
/// reported agent version is >= 7.65.0. Cached so the per-span hot-path is a
/// single atomic load.
static STATS_COMPUTATION_READY: AtomicBool = AtomicBool::new(false);

fn agent_version_ge(version: Option<&str>, req_major: u32, req_minor: u32, req_patch: u32) -> bool {
let Some(v) = version else { return false; };
let v = v.split('-').next().unwrap_or(v); // strip agent version suffixes
let mut parts = v.split('.').filter_map(|p| p.parse::<u32>().ok());
let (Some(major), Some(minor), Some(patch)) = (parts.next(), parts.next(), parts.next()) else { return false; };
(major, minor, patch) >= (req_major, req_minor, req_patch)
}

/// Returns true once the agent /info has been received and applied.
/// Used by the PHP extension to skip stats computation until the concentrator
/// has been properly initialised with peer-tag keys and span kinds.
Expand All @@ -240,6 +253,14 @@ pub extern "C" fn ddog_is_agent_info_ready() -> bool {
AGENT_INFO_RECEIVED.load(Ordering::Acquire)
}

/// Returns true when the agent supports client-side stats computation:
/// agent info has been received, `client_drop_p0s` is true, and the reported
/// agent version is >= 7.65.0.
#[no_mangle]
pub extern "C" fn ddog_agent_has_stats_computation() -> bool {
STATS_COMPUTATION_READY.load(Ordering::Acquire)
}

/// Desired concentrator configuration sourced from the agent's /info endpoint.
/// Populated via `ddog_apply_agent_info`; applied to every concentrator
/// at creation time and when the config changes.
Expand All @@ -253,6 +274,7 @@ static DESIRED_CONFIG: LazyLock<RwLock<DesiredConfig>> = LazyLock::new(|| RwLock

/// Apply updated concentrator config (peer-tag keys, span kinds, trace filters) to
/// `DESIRED_CONFIG` and propagate peer-tag / span-kind changes to all open concentrators.
/// Also updates the `STATS_COMPUTATION_READY` flag based on `client_drop_p0s` and `version`.
pub(crate) fn apply_concentrator_config(
peer_tag_keys: Vec<String>,
span_kinds: Vec<String>,
Expand All @@ -261,12 +283,16 @@ pub(crate) fn apply_concentrator_config(
regex_require: Vec<String>,
regex_reject: Vec<String>,
ignore_resources: Vec<String>,
client_drop_p0s: bool,
version: Option<&str>,
) {
let compiled = trace_filter::compile_trace_filter(
&tags_require, &tags_reject, &regex_require, &regex_reject, &ignore_resources,
);
trace_filter::set_trace_filter(compiled);
AGENT_INFO_RECEIVED.store(true, Ordering::Release);
let ready = client_drop_p0s && agent_version_ge(version, 7, 65, 0);
STATS_COMPUTATION_READY.store(ready, Ordering::Release);
{
let mut dc = DESIRED_CONFIG.write().unwrap();
dc.peer_tag_keys = peer_tag_keys.clone();
Expand Down
4 changes: 2 additions & 2 deletions ext/serializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1534,7 +1534,7 @@ ddog_SpanBytes *ddtrace_serialize_span_to_rust_span(ddtrace_span_data *span, ddo
ZEND_HASH_FOREACH_END();


if (!span_sampling_applied && DDTRACE_G(sidecar) && get_DD_TRACE_STATS_COMPUTATION_ENABLED() && ddog_is_agent_info_ready()) {
if (!span_sampling_applied && DDTRACE_G(sidecar) && get_DD_TRACE_STATS_COMPUTATION_ENABLED() && ddog_agent_has_stats_computation()) {
if (inferred_span) {
// Inferred span won't be serialized, so feed it to the concentrator here.
ddtrace_span_precomputed inferred_pre;
Expand Down Expand Up @@ -1779,7 +1779,7 @@ ddog_SpanBytes *ddtrace_serialize_span_to_rust_span(ddtrace_span_data *span, ddo
zend_string_release(Z_STR(prop_root_service_as_string));
zend_string_release(Z_STR(prop_service_as_string));

if (DDTRACE_G(sidecar) && get_DD_TRACE_STATS_COMPUTATION_ENABLED() && ddog_is_agent_info_ready()) {
if (DDTRACE_G(sidecar) && get_DD_TRACE_STATS_COMPUTATION_ENABLED() && ddog_agent_has_stats_computation()) {
ddtrace_feed_span_to_concentrator(span, &pre);
}

Expand Down
20 changes: 18 additions & 2 deletions tests/ext/request-replayer/client_side_stats.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
Client-side SHM span stats are computed and flushed to the agent on trace flush
--SKIPIF--
<?php include __DIR__ . '/../includes/skipif_no_dev_env.inc'; ?>
<?php
if (PHP_VERSION_ID < 70400) die("skip: Before PHP 7.4, the skip-task would cause the sidecar to fetch the info already.");
if (PHP_VERSION_ID >= 80100) {
echo "nocache\n";
}
$ctx = stream_context_create([
'http' => [
'method' => 'PUT',
'header' => [
'Content-Type: application/json',
'X-Datadog-Test-Session-Token: client_side_stats',
],
'content' => json_encode(['version' => '7.65.0', 'client_drop_p0s' => true]),
]
]);
file_get_contents('http://request-replayer/set-agent-info', false, $ctx);
?>
--ENV--
DD_AGENT_HOST=request-replayer
DD_TRACE_AGENT_PORT=80
Expand All @@ -21,8 +38,7 @@ include __DIR__ . '/../includes/request_replayer.inc';

$rr = new RequestReplayer();

// Block until the sidecar has received the agent's /info response so that
// ddog_is_agent_info_ready() returns true before stats are computed.
// Block until the sidecar has received the agent's /info response before stats are computed
dd_trace_internal_fn('await_agent_info');

$root = \DDTrace\start_trace_span();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ $ctx = stream_context_create([
'Content-Type: application/json',
'X-Datadog-Test-Session-Token: client_side_stats_peer_tags',
],
'content' => '{"peer_tags":["db.hostname"]}',
'content' => json_encode(['version' => '7.65.0', 'client_drop_p0s' => true, 'peer_tags' => ['db.hostname']]),
]
]);
file_get_contents('http://request-replayer/set-agent-info', false, $ctx);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ $ctx = stream_context_create([
'X-Datadog-Test-Session-Token: client_side_stats_trace_filters',
],
'content' => json_encode([
'version' => '7.65.0',
'client_drop_p0s' => true,
'filter_tags' => [
'require' => ['filter_required:yes'],
'reject' => ['filter_reject:yes'],
Expand Down
Loading