55
66#![ deny( warnings) ]
77#![ deny( missing_docs) ]
8+ use std:: path:: Path ;
89use std:: time:: Instant ;
910
1011// Pull in the Antithesis coverage-instrumentation runtime shim only when
@@ -45,10 +46,8 @@ static ALLOC: resource_accounting::TrackingAllocator<std::alloc::System> =
4546async fn main ( ) -> Result < ( ) , GenericError > {
4647 let started = Instant :: now ( ) ;
4748
48- // Initialize the Antithesis SDK as early as possible so assertions and lifecycle hooks register
49- // their catalog before any are evaluated. No-op outside Antithesis and absent in production builds.
5049 #[ cfg( feature = "antithesis" ) ]
51- antithesis_sdk :: antithesis_init ( ) ;
50+ initialize_antithesis ( ) ;
5251
5352 let cli: Cli = argh:: from_env ( ) ;
5453
@@ -61,14 +60,7 @@ async fn main() -> Result<(), GenericError> {
6160 // Load our "bootstrap" configuration -- static configuration on disk or from environment variables -- so we can
6261 // initialize basic subsystems before executing the given subcommand.
6362 let bootstrap_config_path = cli. config_file . unwrap_or_else ( PlatformSettings :: get_config_file_path) ;
64- let bootstrap_config = ConfigurationLoader :: default ( )
65- . with_key_aliases ( KEY_ALIASES )
66- . 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 ( ) ;
63+ let bootstrap_config = load_bootstrap_config ( & bootstrap_config_path) ?. bootstrap_generic ( ) ;
7264
7365 // Translate the bootstrap configuration into ADP's logging configuration, applying ADP-specific rules
7466 // (per-subagent log file key, never sharing a file with the Core Agent).
@@ -122,6 +114,52 @@ async fn main() -> Result<(), GenericError> {
122114 Ok ( ( ) )
123115}
124116
117+ /// Initializes the Antithesis SDK and installs a panic-reporting hook. Set
118+ /// ideally before any panics are possible.
119+ #[ cfg( feature = "antithesis" ) ]
120+ fn initialize_antithesis ( ) {
121+ antithesis_sdk:: antithesis_init ( ) ;
122+
123+ let default_hook = std:: panic:: take_hook ( ) ;
124+ std:: panic:: set_hook ( Box :: new ( move |info| {
125+ let location = info. location ( ) . map_or_else ( String :: new, |l| l. to_string ( ) ) ;
126+ let payload = info. payload ( ) ;
127+ let message = payload
128+ . downcast_ref :: < & str > ( )
129+ . map ( |s| ( * s) . to_string ( ) )
130+ . or_else ( || payload. downcast_ref :: < String > ( ) . cloned ( ) )
131+ . unwrap_or_else ( || "<non-string panic payload>" . to_string ( ) ) ;
132+ antithesis_sdk:: assert_unreachable!(
133+ "agent-data-plane panicked" ,
134+ & serde_json:: json!( { "message" : message, "location" : location } )
135+ ) ;
136+ default_hook ( info) ;
137+ } ) ) ;
138+ }
139+
140+ /// Loads bootstrap configuration from the on-disk file and environment
141+ /// variables.
142+ fn load_bootstrap_config ( bootstrap_config_path : & Path ) -> Result < ConfigurationLoader , GenericError > {
143+ let loaded = ConfigurationLoader :: default ( )
144+ . with_key_aliases ( KEY_ALIASES )
145+ . from_yaml ( bootstrap_config_path)
146+ . error_context ( "Failed to load Datadog Agent configuration file during bootstrap." )
147+ . and_then ( |loader| {
148+ loader
149+ . add_providers ( [ DatadogRemapper :: new ( ) ] )
150+ . from_environment ( PlatformSettings :: get_env_var_prefix ( ) )
151+ . error_context ( "Environment variable prefix should not be empty." )
152+ } ) ;
153+ // A graceful config rejection exits 1 rather than crashing; classify that against a clean boot.
154+ #[ cfg( feature = "antithesis" ) ]
155+ antithesis_sdk:: assert_always_or_unreachable!(
156+ loaded. is_ok( ) ,
157+ "agent-data-plane boots under sampled config" ,
158+ & serde_json:: json!( { "phase" : "config_load" , "error" : loaded. as_ref( ) . err( ) . map( |e| format!( "{e:?}" ) ) } )
159+ ) ;
160+ loaded
161+ }
162+
125163fn parse_metrics_level ( config : & GenericConfiguration ) -> Result < Level , GenericError > {
126164 let raw = config
127165 . try_get_typed :: < String > ( "metrics_level" )
@@ -157,6 +195,13 @@ async fn run_inner(
157195 }
158196 Err ( e) => {
159197 error ! ( "{:?}" , e) ;
198+ // Same boot property as the config-load gate, 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