Skip to content

Commit e7fe98b

Browse files
committed
[host] Simplify get_max_log_level_filter function
- Add more comments and tests to verify the new logic works as expected Signed-off-by: Doru Blânzeanu <dblnz@pm.me>
1 parent e1280c4 commit e7fe98b

1 file changed

Lines changed: 153 additions & 29 deletions

File tree

src/hyperlight_host/src/hypervisor/hyperlight_vm.rs

Lines changed: 153 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,47 +77,71 @@ use crate::sandbox::trace::MemTraceInfo;
7777
use 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.
117141
fn 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

Comments
 (0)