@@ -47,6 +47,9 @@ struct ChunkProcessor {
4747 obfuscation_config : Arc < obfuscation_config:: ObfuscationConfig > ,
4848 tags_provider : Arc < provider:: Provider > ,
4949 span_pointers : Option < Vec < SpanPointer > > ,
50+ /// Pre-computed value of `_dd.compute_stats` for this request: `"1"` if the
51+ /// backend should compute stats, `"0"` if the extension or tracer already did.
52+ compute_stats_value : & ' static str ,
5053}
5154
5255impl TraceChunkProcessor for ChunkProcessor {
@@ -80,6 +83,10 @@ impl TraceChunkProcessor for ChunkProcessor {
8083 span. meta . insert ( "origin" . to_string ( ) , "lambda" . to_string ( ) ) ;
8184 span. meta
8285 . insert ( "_dd.origin" . to_string ( ) , "lambda" . to_string ( ) ) ;
86+ span. meta . insert (
87+ COMPUTE_STATS_KEY . to_string ( ) ,
88+ self . compute_stats_value . to_string ( ) ,
89+ ) ;
8390 obfuscate_span ( span, & self . obfuscation_config ) ;
8491 }
8592
@@ -330,6 +337,20 @@ impl TraceProcessor for ServerlessTraceProcessor {
330337 body_size : usize ,
331338 span_pointers : Option < Vec < SpanPointer > > ,
332339 ) -> ( Option < SendDataBuilderInfo > , TracerPayloadCollection ) {
340+ // Tell the backend whether to compute stats for this request:
341+ // - "1" if neither the tracer nor the extension is computing them
342+ // - "0" if the extension or the tracer has already computed them
343+ let compute_stats_value = if !config. compute_trace_stats_on_extension
344+ && !header_tags. client_computed_stats
345+ {
346+ "1"
347+ } else {
348+ "0"
349+ } ;
350+ debug ! (
351+ "TRACE_PROCESSOR | header_tags.client_computed_stats: {}, compute_stats: {}" ,
352+ header_tags. client_computed_stats, compute_stats_value
353+ ) ;
333354 let mut payload = trace_utils:: collect_pb_trace_chunks (
334355 traces,
335356 & header_tags,
@@ -338,6 +359,7 @@ impl TraceProcessor for ServerlessTraceProcessor {
338359 obfuscation_config : self . obfuscation_config . clone ( ) ,
339360 tags_provider : tags_provider. clone ( ) ,
340361 span_pointers,
362+ compute_stats_value,
341363 } ,
342364 true , // send agentless since we are the agent
343365 )
@@ -350,33 +372,6 @@ impl TraceProcessor for ServerlessTraceProcessor {
350372 let tags = tags_provider. get_function_tags_map ( ) ;
351373 for tracer_payload in collection. iter_mut ( ) {
352374 tracer_payload. tags . extend ( tags. clone ( ) ) ;
353- // 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 {
361- "0"
362- } ;
363- debug ! (
364- "TRACE_PROCESSOR | header_tags.client_computed_stats: {}, compute_stats: {}" ,
365- header_tags. client_computed_stats, compute_stats
366- ) ;
367- tracer_payload
368- . tags
369- . insert ( COMPUTE_STATS_KEY . to_string ( ) , compute_stats. to_string ( ) ) ;
370- // Also propagate to each span's meta so backends that read _dd.compute_stats
371- // from the root span's meta field (rather than the payload-level tags) still
372- // work correctly. This restores the pre-#1118 behavior where the tag was
373- // applied to every span via get_tags_map() / ChunkProcessor.
374- for chunk in & mut tracer_payload. chunks {
375- for span in & mut chunk. spans {
376- span. meta
377- . insert ( COMPUTE_STATS_KEY . to_string ( ) , compute_stats. to_string ( ) ) ;
378- }
379- }
380375 }
381376 }
382377 let endpoint = Endpoint {
@@ -688,11 +683,8 @@ mod tests {
688683 ) ;
689684 let tracer_payload = tracer_payload. expect ( "expected Some payload" ) ;
690685
691- let mut expected_tags = tags_provider. get_function_tags_map ( ) ;
692- // process_traces always sets _dd.compute_stats:"1"
693- // because compute_trace_stats_on_extension is false and client_computed_stats is false.
694- expected_tags. insert ( COMPUTE_STATS_KEY . to_string ( ) , "1" . to_string ( ) ) ;
695- // process_traces also sets _dd.compute_stats on each span's meta.
686+ let expected_tags = tags_provider. get_function_tags_map ( ) ;
687+ // process_traces sets _dd.compute_stats on each span's meta.
696688 let mut expected_span = span. clone ( ) ;
697689 expected_span
698690 . meta
@@ -952,6 +944,7 @@ mod tests {
952944 ) ] ) ,
953945 ) ) ,
954946 span_pointers : None ,
947+ compute_stats_value : "1" ,
955948 } ;
956949
957950 processor. process ( & mut chunk, 0 ) ;
@@ -1036,6 +1029,7 @@ mod tests {
10361029 ) ] ) ,
10371030 ) ) ,
10381031 span_pointers : None ,
1032+ compute_stats_value : "1" ,
10391033 } ;
10401034
10411035 processor. process ( & mut chunk, 0 ) ;
@@ -1119,6 +1113,7 @@ mod tests {
11191113 ) ] ) ,
11201114 ) ) ,
11211115 span_pointers : None ,
1116+ compute_stats_value : "1" ,
11221117 } ;
11231118
11241119 processor. process ( & mut chunk, 0 ) ;
@@ -1527,16 +1522,12 @@ mod tests {
15271522 panic ! ( "expected V07" ) ;
15281523 } ;
15291524 for payload in payloads {
1530- assert_eq ! (
1531- payload
1532- . tags
1533- . get( crate :: tags:: lambda:: tags:: COMPUTE_STATS_KEY ) ,
1534- Some ( & expected_tag. to_string( ) ) ,
1535- "_dd.compute_stats must be {expected_tag} in payload.tags (compute_trace_stats_on_extension={compute_trace_stats_on_extension}, \
1536- client_computed_stats={client_computed_stats})"
1525+ assert ! (
1526+ !payload. tags. contains_key( crate :: tags:: lambda:: tags:: COMPUTE_STATS_KEY ) ,
1527+ "_dd.compute_stats must not be in payload.tags"
15371528 ) ;
1538- // Also verify _dd.compute_stats is set on each span's meta so the backend
1539- // can read it from the root span.
1529+ // _dd.compute_stats is set on each span's meta so the backend can read it
1530+ // from the root span.
15401531 for chunk in & payload. chunks {
15411532 for span in & chunk. spans {
15421533 assert_eq ! (
0 commit comments