Skip to content

Commit ed09dc1

Browse files
lym953claude
andcommitted
feat(traces): propagate client_computed_stats to extension-generated aws.lambda span
When the Go tracer sends its placeholder span (dd-tracer-serverless-span) with Datadog-Client-Computed-Stats: t, store that flag in the invocation Context and pass it through to send_spans so the extension does not double-count stats for the aws.lambda span it generates. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4038775 commit ed09dc1

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

bottlecap/src/lifecycle/invocation/context.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ pub struct Context {
4343
/// tracing.
4444
///
4545
pub extracted_span_context: Option<SpanContext>,
46+
/// Whether the tracer has already computed stats for this invocation.
47+
///
48+
/// Set from the `Datadog-Client-Computed-Stats` header when the tracer's
49+
/// placeholder span (`dd-tracer-serverless-span`) is received.
50+
pub client_computed_stats: bool,
4651
}
4752

4853
/// Struct containing the information needed to reparent a span.
@@ -94,6 +99,7 @@ impl Default for Context {
9499
snapstart_restore_span: None,
95100
tracer_span: None,
96101
extracted_span_context: None,
102+
client_computed_stats: false,
97103
}
98104
}
99105
}
@@ -508,7 +514,12 @@ impl ContextBuffer {
508514

509515
/// Adds the tracer span to a `Context` in the buffer.
510516
///
511-
pub fn add_tracer_span(&mut self, request_id: &String, tracer_span: &Span) {
517+
pub fn add_tracer_span(
518+
&mut self,
519+
request_id: &String,
520+
tracer_span: &Span,
521+
client_computed_stats: bool,
522+
) {
512523
if let Some(context) = self
513524
.buffer
514525
.iter_mut()
@@ -528,6 +539,7 @@ impl ContextBuffer {
528539
.extend(tracer_span.metrics.clone());
529540

530541
context.tracer_span = Some(tracer_span.clone());
542+
context.client_computed_stats = client_computed_stats;
531543
} else {
532544
debug!("Could not add tracer span - context not found");
533545
}

bottlecap/src/lifecycle/invocation/processor.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -610,9 +610,16 @@ impl Processor {
610610
trace_sender: &Arc<SendingTraceProcessor>,
611611
context: Context,
612612
) {
613+
let client_computed_stats = context.client_computed_stats;
613614
let (traces, body_size) = self.get_ctx_spans(context);
614-
self.send_spans(traces, body_size, tags_provider, trace_sender)
615-
.await;
615+
self.send_spans(
616+
traces,
617+
body_size,
618+
client_computed_stats,
619+
tags_provider,
620+
trace_sender,
621+
)
622+
.await;
616623
}
617624

618625
fn get_ctx_spans(&mut self, context: Context) -> (Vec<Span>, usize) {
@@ -677,7 +684,7 @@ impl Processor {
677684
let traces = vec![cold_start_span.clone()];
678685
let body_size = size_of_val(cold_start_span);
679686

680-
self.send_spans(traces, body_size, tags_provider, trace_sender)
687+
self.send_spans(traces, body_size, false, tags_provider, trace_sender)
681688
.await;
682689
}
683690
}
@@ -689,6 +696,7 @@ impl Processor {
689696
&mut self,
690697
traces: Vec<Span>,
691698
body_size: usize,
699+
client_computed_stats: bool,
692700
tags_provider: &Arc<provider::Provider>,
693701
trace_sender: &Arc<SendingTraceProcessor>,
694702
) {
@@ -701,7 +709,7 @@ impl Processor {
701709
tracer_version: "",
702710
container_id: "",
703711
client_computed_top_level: false,
704-
client_computed_stats: false,
712+
client_computed_stats,
705713
dropped_p0_traces: 0,
706714
dropped_p0_spans: 0,
707715
};
@@ -1337,9 +1345,10 @@ impl Processor {
13371345
///
13381346
/// This is used to enrich the invocation span with additional metadata from the tracers
13391347
/// top level span, since we discard the tracer span when we create the invocation span.
1340-
pub fn add_tracer_span(&mut self, span: &Span) {
1348+
pub fn add_tracer_span(&mut self, span: &Span, client_computed_stats: bool) {
13411349
if let Some(request_id) = span.meta.get("request_id") {
1342-
self.context_buffer.add_tracer_span(request_id, span);
1350+
self.context_buffer
1351+
.add_tracer_span(request_id, span, client_computed_stats);
13431352
}
13441353
}
13451354
}

bottlecap/src/lifecycle/invocation/processor_service.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ pub enum ProcessorCommand {
110110
},
111111
AddTracerSpan {
112112
span: Box<Span>,
113+
client_computed_stats: bool,
113114
},
114115
OnOutOfMemoryError {
115116
timestamp: i64,
@@ -372,10 +373,12 @@ impl InvocationProcessorHandle {
372373
pub async fn add_tracer_span(
373374
&self,
374375
span: Span,
376+
client_computed_stats: bool,
375377
) -> Result<(), mpsc::error::SendError<ProcessorCommand>> {
376378
self.sender
377379
.send(ProcessorCommand::AddTracerSpan {
378380
span: Box::new(span),
381+
client_computed_stats,
379382
})
380383
.await
381384
}
@@ -585,8 +588,11 @@ impl InvocationProcessorService {
585588
let result = Ok(self.processor.set_cold_start_span_trace_id(trace_id));
586589
let _ = response.send(result);
587590
}
588-
ProcessorCommand::AddTracerSpan { span } => {
589-
self.processor.add_tracer_span(&span);
591+
ProcessorCommand::AddTracerSpan {
592+
span,
593+
client_computed_stats,
594+
} => {
595+
self.processor.add_tracer_span(&span, client_computed_stats);
590596
}
591597
ProcessorCommand::OnOutOfMemoryError { timestamp } => {
592598
self.processor.on_out_of_memory_error(timestamp);

bottlecap/src/traces/trace_agent.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,8 @@ impl TraceAgent {
501501
);
502502
}
503503

504-
let tracer_header_tags = (&parts.headers).into();
504+
let tracer_header_tags: libdd_trace_utils::tracer_header_tags::TracerHeaderTags<'_> =
505+
(&parts.headers).into();
505506

506507
let (body_size, mut traces): (usize, Vec<Vec<pb::Span>>) = match version {
507508
ApiVersion::V04 => {
@@ -531,7 +532,6 @@ impl TraceAgent {
531532
}
532533
},
533534
};
534-
535535
let mut reparenting_info = match invocation_processor_handle.get_reparenting_info().await {
536536
Ok(info) => info,
537537
Err(e) => {
@@ -586,7 +586,7 @@ impl TraceAgent {
586586

587587
if span.resource == INVOCATION_SPAN_RESOURCE
588588
&& let Err(e) = invocation_processor_handle
589-
.add_tracer_span(span.clone())
589+
.add_tracer_span(span.clone(), tracer_header_tags.client_computed_stats)
590590
.await
591591
{
592592
error!("Failed to add tracer span to processor: {}", e);

0 commit comments

Comments
 (0)