@@ -50,6 +50,30 @@ async fn main() -> Result<(), GenericError> {
5050 #[ cfg( feature = "antithesis" ) ]
5151 antithesis_sdk:: antithesis_init ( ) ;
5252
53+ // Report any panic to Antithesis before the process aborts. The antithesis build sets
54+ // `panic = "abort"`, and the captured container logs do not surface ADP's stderr, so the default
55+ // panic message is invisible in triage. Route the panic payload and site through the SDK, which
56+ // writes to sdk.jsonl -- a channel that survives the abort -- then chain to the default hook so a
57+ // local build still prints normally.
58+ #[ cfg( feature = "antithesis" ) ]
59+ {
60+ let default_hook = std:: panic:: take_hook ( ) ;
61+ std:: panic:: set_hook ( Box :: new ( move |info| {
62+ let location = info. location ( ) . map_or_else ( String :: new, |l| l. to_string ( ) ) ;
63+ let payload = info. payload ( ) ;
64+ let message = payload
65+ . downcast_ref :: < & str > ( )
66+ . map ( |s| ( * s) . to_string ( ) )
67+ . or_else ( || payload. downcast_ref :: < String > ( ) . cloned ( ) )
68+ . unwrap_or_else ( || "<non-string panic payload>" . to_string ( ) ) ;
69+ antithesis_sdk:: assert_unreachable!(
70+ "agent-data-plane panicked" ,
71+ & serde_json:: json!( { "message" : message, "location" : location } )
72+ ) ;
73+ default_hook ( info) ;
74+ } ) ) ;
75+ }
76+
5377 let cli: Cli = argh:: from_env ( ) ;
5478
5579 // Print version and exit early without requiring config.
@@ -61,14 +85,27 @@ async fn main() -> Result<(), GenericError> {
6185 // Load our "bootstrap" configuration -- static configuration on disk or from environment variables -- so we can
6286 // initialize basic subsystems before executing the given subcommand.
6387 let bootstrap_config_path = cli. config_file . unwrap_or_else ( PlatformSettings :: get_config_file_path) ;
64- let bootstrap_config = ConfigurationLoader :: default ( )
88+ let loaded = ConfigurationLoader :: default ( )
6589 . with_key_aliases ( KEY_ALIASES )
6690 . from_yaml ( & bootstrap_config_path)
67- . error_context ( "Failed to load Datadog Agent configuration file during bootstrap." ) ?
68- . add_providers ( [ DatadogRemapper :: new ( ) ] )
69- . from_environment ( PlatformSettings :: get_env_var_prefix ( ) )
70- . error_context ( "Environment variable prefix should not be empty." ) ?
71- . bootstrap_generic ( ) ;
91+ . error_context ( "Failed to load Datadog Agent configuration file during bootstrap." )
92+ . and_then ( |loader| {
93+ loader
94+ . add_providers ( [ DatadogRemapper :: new ( ) ] )
95+ . from_environment ( PlatformSettings :: get_env_var_prefix ( ) )
96+ . error_context ( "Environment variable prefix should not be empty." )
97+ } ) ;
98+
99+ // Classify a graceful config rejection (process exit 1) versus a clean boot. A false evaluation
100+ // carries the rejection reason, so triage shows which sampled `datadog.yaml` ADP refused and why.
101+ #[ cfg( feature = "antithesis" ) ]
102+ antithesis_sdk:: assert_always_or_unreachable!(
103+ loaded. is_ok( ) ,
104+ "agent-data-plane boots under sampled config" ,
105+ & serde_json:: json!( { "phase" : "config_load" , "error" : loaded. as_ref( ) . err( ) . map( |e| format!( "{e:?}" ) ) } )
106+ ) ;
107+
108+ let bootstrap_config = loaded?. bootstrap_generic ( ) ;
72109
73110 // Translate the bootstrap configuration into ADP's logging configuration, applying ADP-specific rules
74111 // (per-subagent log file key, never sharing a file with the Core Agent).
@@ -157,6 +194,14 @@ async fn run_inner(
157194 }
158195 Err ( e) => {
159196 error ! ( "{:?}" , e) ;
197+ // Same property as the config-load gate: a run-setup error is also a graceful
198+ // exit-1 under this sampled config, distinguished by `phase` in the details.
199+ #[ cfg( feature = "antithesis" ) ]
200+ antithesis_sdk:: assert_always_or_unreachable!(
201+ false ,
202+ "agent-data-plane boots under sampled config" ,
203+ & serde_json:: json!( { "phase" : "run_setup" , "error" : format!( "{e:?}" ) } )
204+ ) ;
160205 Some ( 1 )
161206 }
162207 } ;
0 commit comments