@@ -351,14 +351,19 @@ impl TraceProcessor for ServerlessTraceProcessor {
351351 for tracer_payload in collection. iter_mut ( ) {
352352 tracer_payload. tags . extend ( tags. clone ( ) ) ;
353353 // Tell the backend whether to compute stats:
354- // - "1" (compute on backend) if neither the tracer nor the extension is computing them
355- // - "0" (skip on backend) if the extension or the tracer has already computed them
356- let compute_stats = if !config. compute_trace_stats_on_extension
357- && !header_tags. client_computed_stats
358- {
359- "1"
360- } else {
354+ // - "1" (compute on backend) if the extension is NOT computing stats
355+ // - "0" (skip on backend) if the extension is computing stats
356+ //
357+ // We intentionally ignore client_computed_stats here to keep
358+ // the backend as a safety net. If the tracer claims it computed
359+ // stats but they don't actually reach the backend, setting this
360+ // to "0" would cause stats to disappear entirely.
361+ // This may lead to double-counting when the tracer also sends
362+ // stats, but that is preferable to zero stats.
363+ let compute_stats = if config. compute_trace_stats_on_extension {
361364 "0"
365+ } else {
366+ "1"
362367 } ;
363368 tracer_payload
364369 . tags
@@ -1400,7 +1405,7 @@ mod tests {
14001405 /// | Input: `compute_trace_stats_on_extension` | Input: `client_computed_stats` | Expected: `_dd.compute_stats` | Expected: Extension generates stats? |
14011406 /// |-------------------------------------------|--------------------------------|-------------------------------|--------------------------------------|
14021407 /// | `false` | `false` | `"1"` | No |
1403- /// | `false` | `true` | `"0 "` | No |
1408+ /// | `false` | `true` | `"1 "` | No |
14041409 /// | `true` | `false` | `"0"` | Yes |
14051410 /// | `true` | `true` | `"0"` | No |
14061411 #[ allow( clippy:: unwrap_used) ]
@@ -1414,11 +1419,12 @@ mod tests {
14141419 use libdd_trace_obfuscation:: obfuscation_config:: ObfuscationConfig ;
14151420 use tokio:: sync:: mpsc;
14161421
1417- // "_dd.compute_stats" is "1" only when neither side computes stats (backend must do it).
1418- let expected_tag = if !compute_trace_stats_on_extension && !client_computed_stats {
1419- "1"
1420- } else {
1422+ // "_dd.compute_stats" is "1" when the extension is NOT computing stats (backend must do it).
1423+ // client_computed_stats does NOT affect this tag — the backend is the safety net.
1424+ let expected_tag = if compute_trace_stats_on_extension {
14211425 "0"
1426+ } else {
1427+ "1"
14221428 } ;
14231429 // The extension generates stats only when it is configured to do so and the tracer hasn't.
14241430 let expect_stats = compute_trace_stats_on_extension && !client_computed_stats;
@@ -1529,7 +1535,8 @@ mod tests {
15291535 #[ tokio:: test]
15301536 #[ allow( clippy:: unwrap_used) ]
15311537 async fn test_compute_stats_tag_tracer_computes ( ) {
1532- // Tracer computed stats (Datadog-Client-Computed-Stats header set) → tag "0".
1538+ // Tracer computed stats (Datadog-Client-Computed-Stats header set) → tag "1".
1539+ // Backend still computes as a safety net; extension skips its own stats generation.
15331540 check_compute_stats_behavior ( false , true ) . await ;
15341541 }
15351542
0 commit comments