@@ -65,6 +65,7 @@ pub struct TraceExporterConfig {
65
65
input_format : TraceExporterInputFormat ,
66
66
output_format : TraceExporterOutputFormat ,
67
67
compute_stats : bool ,
68
+ client_computed_stats : bool ,
68
69
telemetry_cfg : Option < TelemetryConfig > ,
69
70
test_session_token : Option < String > ,
70
71
}
@@ -275,6 +276,31 @@ pub unsafe extern "C" fn ddog_trace_exporter_config_set_compute_stats(
275
276
}
276
277
}
277
278
279
+ /// Sets `Datadog-Client-Computed-Stats` header to `true`.
280
+ /// This indicates that the upstream system has already computed the stats,
281
+ /// and no further stats computation should be performed.
282
+ ///
283
+ /// <div class="warning">
284
+ /// This method must not be used when `compute_stats` is enabled, as it could
285
+ /// result in duplicate stats computation.
286
+ /// </div>
287
+ ///
288
+ /// A common use case is in Application Security Monitoring (ASM) scenarios:
289
+ /// when APM is disabled but ASM is enabled, setting this header to `true`
290
+ /// ensures that no stats are computed at any level (exporter or agent).
291
+ #[ no_mangle]
292
+ pub unsafe extern "C" fn ddog_trace_exporter_config_set_client_computed_stats (
293
+ config : Option < & mut TraceExporterConfig > ,
294
+ client_computed_stats : bool ,
295
+ ) -> Option < Box < ExporterError > > {
296
+ if let Option :: Some ( config) = config {
297
+ config. client_computed_stats = client_computed_stats;
298
+ None
299
+ } else {
300
+ gen_error ! ( ErrorCode :: InvalidArgument )
301
+ }
302
+ }
303
+
278
304
/// Sets the `X-Datadog-Test-Session-Token` header. Only used for testing with the test agent.
279
305
#[ no_mangle]
280
306
pub unsafe extern "C" fn ddog_trace_exporter_config_set_test_session_token (
@@ -325,6 +351,8 @@ pub unsafe extern "C" fn ddog_trace_exporter_new(
325
351
. set_output_format ( config. output_format ) ;
326
352
if config. compute_stats {
327
353
builder. enable_stats ( Duration :: from_secs ( 10 ) ) ;
354
+ } else if config. client_computed_stats {
355
+ builder. set_client_computed_stats ( ) ;
328
356
}
329
357
330
358
if let Some ( cfg) = & config. telemetry_cfg {
@@ -610,6 +638,24 @@ mod tests {
610
638
}
611
639
}
612
640
641
+ #[ test]
642
+ fn config_client_computed_stats_test ( ) {
643
+ unsafe {
644
+ let error = ddog_trace_exporter_config_set_client_computed_stats ( None , true ) ;
645
+ assert_eq ! ( error. as_ref( ) . unwrap( ) . code, ErrorCode :: InvalidArgument ) ;
646
+
647
+ ddog_trace_exporter_error_free ( error) ;
648
+
649
+ let mut config = Some ( TraceExporterConfig :: default ( ) ) ;
650
+ let error = ddog_trace_exporter_config_set_client_computed_stats ( config. as_mut ( ) , true ) ;
651
+
652
+ assert_eq ! ( error, None ) ;
653
+
654
+ let cfg = config. unwrap ( ) ;
655
+ assert ! ( cfg. client_computed_stats) ;
656
+ }
657
+ }
658
+
613
659
#[ test]
614
660
fn config_telemetry_test ( ) {
615
661
unsafe {
@@ -781,6 +827,7 @@ mod tests {
781
827
compute_stats : false ,
782
828
telemetry_cfg : None ,
783
829
test_session_token : None ,
830
+ client_computed_stats : false ,
784
831
} ;
785
832
786
833
let mut ptr: MaybeUninit < Box < TraceExporter > > = MaybeUninit :: uninit ( ) ;
@@ -851,6 +898,7 @@ mod tests {
851
898
compute_stats : false ,
852
899
telemetry_cfg : None ,
853
900
test_session_token : None ,
901
+ client_computed_stats : false ,
854
902
} ;
855
903
856
904
let mut ptr: MaybeUninit < Box < TraceExporter > > = MaybeUninit :: uninit ( ) ;
@@ -927,6 +975,7 @@ mod tests {
927
975
debug_enabled : true ,
928
976
} ) ,
929
977
test_session_token : None ,
978
+ client_computed_stats : false ,
930
979
} ;
931
980
932
981
let mut ptr: MaybeUninit < Box < TraceExporter > > = MaybeUninit :: uninit ( ) ;
0 commit comments