@@ -24,7 +24,7 @@ pub enum StacktraceCollection {
24
24
EnabledWithSymbolsInReceiver ,
25
25
}
26
26
27
- #[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
27
+ #[ derive( Debug , Clone , PartialEq , Serialize ) ]
28
28
pub struct CrashtrackerConfiguration {
29
29
// Paths to any additional files to track, if any
30
30
additional_files : Vec < String > ,
@@ -223,6 +223,50 @@ impl CrashtrackerConfiguration {
223
223
}
224
224
}
225
225
226
+ impl < ' de > serde:: Deserialize < ' de > for CrashtrackerConfiguration {
227
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
228
+ where
229
+ D : serde:: Deserializer < ' de > ,
230
+ {
231
+ #[ derive( Deserialize ) ]
232
+ struct CrashtrackerConfigurationHelper {
233
+ additional_files : Vec < String > ,
234
+ create_alt_stack : bool ,
235
+ demangle_names : bool ,
236
+ endpoint : Option < Endpoint > ,
237
+ resolve_frames : StacktraceCollection ,
238
+ secondary_endpoint : Option < Endpoint > ,
239
+ signals : Vec < i32 > ,
240
+ timeout : Duration ,
241
+ unix_socket_path : Option < String > ,
242
+ use_alt_stack : bool ,
243
+ }
244
+
245
+ let helper = CrashtrackerConfigurationHelper :: deserialize ( deserializer) ?;
246
+
247
+ // Apply secondary endpoint derivation logic during deserialization
248
+ let secondary_endpoint = helper. secondary_endpoint . or_else ( || {
249
+ helper
250
+ . endpoint
251
+ . as_ref ( )
252
+ . and_then ( derive_default_secondary_endpoint)
253
+ } ) ;
254
+
255
+ Ok ( CrashtrackerConfiguration {
256
+ additional_files : helper. additional_files ,
257
+ create_alt_stack : helper. create_alt_stack ,
258
+ demangle_names : helper. demangle_names ,
259
+ endpoint : helper. endpoint ,
260
+ resolve_frames : helper. resolve_frames ,
261
+ secondary_endpoint,
262
+ signals : helper. signals ,
263
+ timeout : helper. timeout ,
264
+ unix_socket_path : helper. unix_socket_path ,
265
+ use_alt_stack : helper. use_alt_stack ,
266
+ } )
267
+ }
268
+ }
269
+
226
270
/// Derives a default secondary endpoint based on the primary endpoint.
227
271
/// This mirrors the primary endpoint logic but uses Error Tracking endpoints.
228
272
fn derive_default_secondary_endpoint ( primary : & Endpoint ) -> Option < Endpoint > {
@@ -511,4 +555,40 @@ mod tests {
511
555
512
556
Ok ( ( ) )
513
557
}
558
+
559
+ #[ test]
560
+ fn test_deserialize_with_secondary_endpoint_derivation ( ) -> anyhow:: Result < ( ) > {
561
+ use ddcommon:: Endpoint ;
562
+ use std:: time:: Duration ;
563
+
564
+ // Create a config with primary endpoint, serialize it without secondary
565
+ let mut original_config = super :: CrashtrackerConfiguration :: new (
566
+ vec ! [ ] ,
567
+ false ,
568
+ false ,
569
+ Some ( Endpoint :: from_slice ( "https://intake.profile.datadoghq.com" ) ) ,
570
+ super :: StacktraceCollection :: Disabled ,
571
+ vec ! [ ] ,
572
+ Some ( Duration :: from_secs ( 1 ) ) ,
573
+ None ,
574
+ false ,
575
+ ) ?;
576
+
577
+ // Clear the secondary endpoint to simulate receiving from collector
578
+ original_config. secondary_endpoint = None ;
579
+
580
+ // Serialize and then deserialize
581
+ let serialized = serde_json:: to_string ( & original_config) ?;
582
+ let deserialized: super :: CrashtrackerConfiguration = serde_json:: from_str ( & serialized) ?;
583
+
584
+ // Verify that deserialization applied secondary endpoint derivation
585
+ assert ! ( deserialized. secondary_endpoint( ) . is_some( ) ) ;
586
+ let secondary = deserialized. secondary_endpoint ( ) . as_ref ( ) . unwrap ( ) ;
587
+ assert_eq ! (
588
+ secondary. url. to_string( ) ,
589
+ "https://event-platform-intake.datad0g.com/api/v2/errorsintake"
590
+ ) ;
591
+
592
+ Ok ( ( ) )
593
+ }
514
594
}
0 commit comments