Skip to content

Commit cb3ce6d

Browse files
lym953claude
andcommitted
fix(traces): restore _dd.compute_stats on span meta to fix missing trace.aws.lambda.hits
PR #1118 moved `_dd.compute_stats` from each span's `meta` (applied via `get_tags_map()` / `ChunkProcessor`) to the payload-level `tracer_payload.tags` only. The Datadog APM backend reads this signal from the root span's `meta` field, not from the payload-level tags, so it stopped computing stats and `trace.aws.lambda.hits` disappeared from the trace explorer. Fix: propagate `_dd.compute_stats` to every span's `meta` in the same loop that writes it to `tracer_payload.tags`, restoring the pre-#1118 behavior while keeping the payload-level tag as well. Also add debug logging to `handle_traces` to surface the header tags on every incoming trace request, which aids diagnosing similar issues. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 29e1215 commit cb3ce6d

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

bottlecap/src/traces/trace_agent.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ impl TraceAgent {
323323
}
324324

325325
async fn stats(State(state): State<StatsState>, request: Request) -> Response {
326+
debug!("TRACE_AGENT | stats request: {request:?}");
326327
match state
327328
.stats_processor
328329
.process_stats(request, state.stats_tx)
@@ -504,6 +505,8 @@ impl TraceAgent {
504505
let tracer_header_tags: libdd_trace_utils::tracer_header_tags::TracerHeaderTags<'_> =
505506
(&parts.headers).into();
506507

508+
debug!("TRACE_AGENT | tracer_header_tags: {tracer_header_tags:?}");
509+
507510
let (body_size, mut traces): (usize, Vec<Vec<pb::Span>>) = match version {
508511
ApiVersion::V04 => {
509512
match trace_utils::get_traces_from_request_body(http_common::Body::from_bytes(body))

bottlecap/src/traces/trace_processor.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,20 @@ impl TraceProcessor for ServerlessTraceProcessor {
360360
} else {
361361
"0"
362362
};
363+
debug!("TRACE_PROCESSOR | header_tags.client_computed_stats: {}, compute_stats: {}", header_tags.client_computed_stats, compute_stats);
363364
tracer_payload
364365
.tags
365366
.insert(COMPUTE_STATS_KEY.to_string(), compute_stats.to_string());
367+
// Also propagate to each span's meta so backends that read _dd.compute_stats
368+
// from the root span's meta field (rather than the payload-level tags) still
369+
// work correctly. This restores the pre-#1118 behavior where the tag was
370+
// applied to every span via get_tags_map() / ChunkProcessor.
371+
for chunk in &mut tracer_payload.chunks {
372+
for span in &mut chunk.spans {
373+
span.meta
374+
.insert(COMPUTE_STATS_KEY.to_string(), compute_stats.to_string());
375+
}
376+
}
366377
}
367378
}
368379
let endpoint = Endpoint {
@@ -1513,9 +1524,21 @@ mod tests {
15131524
.tags
15141525
.get(crate::tags::lambda::tags::COMPUTE_STATS_KEY),
15151526
Some(&expected_tag.to_string()),
1516-
"_dd.compute_stats must be {expected_tag} (compute_trace_stats_on_extension={compute_trace_stats_on_extension}, \
1527+
"_dd.compute_stats must be {expected_tag} in payload.tags (compute_trace_stats_on_extension={compute_trace_stats_on_extension}, \
15171528
client_computed_stats={client_computed_stats})"
15181529
);
1530+
// Also verify _dd.compute_stats is set on each span's meta so the backend
1531+
// can read it from the root span.
1532+
for chunk in &payload.chunks {
1533+
for span in &chunk.spans {
1534+
assert_eq!(
1535+
span.meta.get(crate::tags::lambda::tags::COMPUTE_STATS_KEY),
1536+
Some(&expected_tag.to_string()),
1537+
"_dd.compute_stats must be {expected_tag} in span.meta (compute_trace_stats_on_extension={compute_trace_stats_on_extension}, \
1538+
client_computed_stats={client_computed_stats})"
1539+
);
1540+
}
1541+
}
15191542
}
15201543
}
15211544

0 commit comments

Comments
 (0)