@@ -77,47 +77,71 @@ use crate::sandbox::trace::MemTraceInfo;
7777use crate :: sandbox:: uninitialized:: SandboxRuntimeConfig ;
7878
7979/// Get the logging level filter to pass to the guest entrypoint
80- fn get_max_log_level_filter ( ) -> LevelFilter {
81- // Check to see if the RUST_LOG environment variable is set
82- // and if so, parse it to get the log_level for hyperlight_guest
83- // if that is not set get the log level for the hyperlight_host
84-
80+ ///
81+ /// The guest entrypoint uses this to determine the maximum log level to enable for the guest.
82+ /// The `RUST_LOG` environment variable is expected to be in the format of comma-separated
83+ /// key-value pairs, where the key is a log target (e.g., "hyperlight_guest_bin") and the value is
84+ /// a log level (e.g., "debug").
85+ ///
86+ /// NOTE: This prioritizes the log level for the targets containing "hyperlight_guest" string, then
87+ /// "hyperlight_host", and then general log level. If none of these targets are found, it
88+ /// defaults to "error".
89+ ///
90+ /// # Example
91+ /// ```rust
92+ /// RUST_LOG="trace,hyperlight_guest=debug,hyperlight_host=info,hyperlight_guest_bin=trace"
93+ /// let filter = get_max_log_level_filter(RUST_LOG);
94+ /// assert_eq!(filter, LevelFilter::DEBUG, "Max log level should be Debug");
95+ /// ```
96+ fn get_max_log_level_filter ( rust_log : String ) -> LevelFilter {
8597 // This is done as the guest will produce logs based on the log level returned here
8698 // producing those logs is expensive and we don't want to do it if the host is not
8799 // going to process them
100+ let level_str = rust_log
101+ . split ( ',' )
102+ // Prioritize targets containing "hyperlight_guest"
103+ . find_map ( |part| {
104+ let mut kv = part. splitn ( 2 , '=' ) ;
105+ match ( kv. next ( ) , kv. next ( ) ) {
106+ ( Some ( k) , Some ( v) ) if k. trim ( ) . contains ( "hyperlight_guest" ) => Some ( v. trim ( ) ) ,
107+ _ => None ,
108+ }
109+ } )
110+ // Then check for "hyperlight_host"
111+ . or_else ( || {
112+ rust_log. split ( ',' ) . find_map ( |part| {
113+ let mut kv = part. splitn ( 2 , '=' ) ;
114+ match ( kv. next ( ) , kv. next ( ) ) {
115+ ( Some ( k) , Some ( v) ) if k. trim ( ) . contains ( "hyperlight_host" ) => Some ( v. trim ( ) ) ,
116+ _ => None ,
117+ }
118+ } )
119+ } )
120+ // Finally, check for general log level
121+ . or_else ( || {
122+ rust_log. split ( ',' ) . find_map ( |part| {
123+ if part. contains ( "=" ) {
124+ None
125+ } else {
126+ Some ( part. trim ( ) )
127+ }
128+ } )
129+ } )
130+ . unwrap_or ( "" ) ;
88131
89- let val = std:: env:: var ( "RUST_LOG" ) . unwrap_or_default ( ) ;
90-
91- let level = if val. contains ( "hyperlight_guest" ) {
92- val. split ( ',' )
93- . find ( |s| s. contains ( "hyperlight_guest" ) )
94- . unwrap_or ( "" )
95- . split ( '=' )
96- . nth ( 1 )
97- . unwrap_or ( "" )
98- } else if val. contains ( "hyperlight_host" ) {
99- val. split ( ',' )
100- . find ( |s| s. contains ( "hyperlight_host" ) )
101- . unwrap_or ( "" )
102- . split ( '=' )
103- . nth ( 1 )
104- . unwrap_or ( "" )
105- } else {
106- // look for a value string that does not contain "="
107- val. split ( ',' ) . find ( |s| !s. contains ( "=" ) ) . unwrap_or ( "" )
108- } ;
132+ tracing:: info!( "Determined guest log level: {}" , level_str) ;
109133
110- tracing:: info!( "Determined guest log level: {}" , level) ;
111- // Convert the log level string to a LevelFilter
112134 // If no value is found, default to Error
113- LevelFilter :: from_str ( level ) . unwrap_or ( LevelFilter :: ERROR )
135+ LevelFilter :: from_str ( level_str ) . unwrap_or ( LevelFilter :: ERROR )
114136}
115137
116138/// Converts a given [`Option<LevelFilter>`] to a `u64` value to be passed to the guest entrypoint
139+ /// If the provided filter is `None`, it uses the `RUST_LOG` environment variable to determine the
140+ /// maximum log level filter for the guest and converts it to a `u64` value.
117141fn get_guest_log_filter ( guest_max_log_level : Option < LevelFilter > ) -> u64 {
118142 let guest_log_level_filter = match guest_max_log_level {
119143 Some ( level) => level,
120- None => get_max_log_level_filter ( ) ,
144+ None => get_max_log_level_filter ( std :: env :: var ( "RUST_LOG" ) . unwrap_or_default ( ) ) ,
121145 } ;
122146 GuestLogFilter :: from ( guest_log_level_filter) . into ( )
123147}
@@ -2859,4 +2883,104 @@ mod tests {
28592883 FxsaveTestContext { ctx, fxsave_offset }
28602884 }
28612885 }
2886+
2887+ /// ========================================================================
2888+ /// Misc tests
2889+ /// ========================================================================
2890+ #[ test]
2891+ fn test_get_max_log_level_filter_both_guest_and_host ( ) {
2892+ let rust_log = "hyperlight_guest=trace,hyperlight_host=debug" . to_string ( ) ;
2893+ let filter = get_max_log_level_filter ( rust_log) ;
2894+
2895+ assert_eq ! ( filter, LevelFilter :: TRACE , "Max log level should be Trace" ) ;
2896+ }
2897+ #[ test]
2898+ fn test_get_max_log_level_filter_only_guest ( ) {
2899+ let rust_log = "hyperlight_guest=info" . to_string ( ) ;
2900+ let filter = get_max_log_level_filter ( rust_log) ;
2901+
2902+ assert_eq ! ( filter, LevelFilter :: INFO , "Max log level should be Info" ) ;
2903+ }
2904+ #[ test]
2905+ fn test_get_max_log_level_filter_only_host ( ) {
2906+ let rust_log = "hyperlight_host=debug" . to_string ( ) ;
2907+ let filter = get_max_log_level_filter ( rust_log) ;
2908+
2909+ assert_eq ! ( filter, LevelFilter :: DEBUG , "Max log level should be Debug" ) ;
2910+ }
2911+ #[ test]
2912+ fn test_get_max_log_level_filter_only_general ( ) {
2913+ let rust_log = "trace" . to_string ( ) ;
2914+ let filter = get_max_log_level_filter ( rust_log) ;
2915+
2916+ assert_eq ! ( filter, LevelFilter :: TRACE , "Max log level should be Trace" ) ;
2917+ }
2918+ #[ test]
2919+ fn test_get_max_log_level_filter_complex_rust_log_00 ( ) {
2920+ let rust_log =
2921+ "error,hyperlight_guest=debug,hyperlight_host=info,hyperlight_guest_bin=trace"
2922+ . to_string ( ) ;
2923+ let filter = get_max_log_level_filter ( rust_log) ;
2924+
2925+ assert_eq ! ( filter, LevelFilter :: DEBUG , "Max log level should be Debug" ) ;
2926+ }
2927+ #[ test]
2928+ fn test_get_max_log_level_filter_complex_rust_log_01 ( ) {
2929+ let rust_log =
2930+ "error,hyperlight_host=info,hyperlight_guest=debug,hyperlight_guest_bin=trace"
2931+ . to_string ( ) ;
2932+ let filter = get_max_log_level_filter ( rust_log) ;
2933+
2934+ assert_eq ! ( filter, LevelFilter :: DEBUG , "Max log level should be Debug" ) ;
2935+ }
2936+ #[ test]
2937+ fn test_get_max_log_level_filter_complex_rust_log_02 ( ) {
2938+ let rust_log =
2939+ "hyperlight_host=info,error,hyperlight_guest=debug,hyperlight_guest_bin=trace"
2940+ . to_string ( ) ;
2941+ let filter = get_max_log_level_filter ( rust_log) ;
2942+
2943+ assert_eq ! ( filter, LevelFilter :: DEBUG , "Max log level should be Debug" ) ;
2944+ }
2945+ #[ test]
2946+ fn test_get_max_log_level_filter_general_and_others ( ) {
2947+ let rust_log =
2948+ "trace,hyperlight_component_macro=debug,hyperlight_component_util=error" . to_string ( ) ;
2949+ let filter = get_max_log_level_filter ( rust_log) ;
2950+
2951+ assert_eq ! ( filter, LevelFilter :: TRACE , "Max log level should be Trace" ) ;
2952+ }
2953+ #[ test]
2954+ fn test_get_max_log_level_filter_default ( ) {
2955+ let rust_log = "hyperlight_common=debug,hyperlight_component_util=info" . to_string ( ) ;
2956+ let filter = get_max_log_level_filter ( rust_log) ;
2957+
2958+ assert_eq ! (
2959+ filter,
2960+ LevelFilter :: ERROR ,
2961+ "Max log level should default to Error"
2962+ ) ;
2963+ }
2964+ #[ test]
2965+ fn test_get_max_log_level_filter_invalid_rust_log ( ) {
2966+ let rust_log = "this is an invalid rust log string" . to_string ( ) ;
2967+ let filter = get_max_log_level_filter ( rust_log) ;
2968+
2969+ assert_eq ! (
2970+ filter,
2971+ LevelFilter :: ERROR ,
2972+ "Max log level should default to Error"
2973+ ) ;
2974+ }
2975+ #[ test]
2976+ fn test_get_max_log_level_filter_empty_rust_log ( ) {
2977+ let rust_log = "" . to_string ( ) ;
2978+ let filter = get_max_log_level_filter ( rust_log) ;
2979+
2980+ assert_eq ! (
2981+ filter,
2982+ LevelFilter :: ERROR ,
2983+ "Max log level should default to Error"
2984+ ) ;
2985+ }
28622986}
0 commit comments