xref: /cloud-hypervisor/src/lib.rs (revision 190a11f2124b0b60a2d44e85b7c9988373acfb6d)
1 // Copyright © 2025 Cyberus Technology GmbH
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 
5 use std::error::Error;
6 
7 /// Prints a chain of errors to the user in a consistent manner.
8 /// The user will see a clear chain of errors, followed by debug output
9 /// for opening issues.
cli_print_error_chain<'a>( top_error: &'a (dyn Error + 'static), component: &str, display_modifier: impl Fn( usize, usize, &'a (dyn Error + 'static), ) -> Option<String>, )10 pub fn cli_print_error_chain<'a>(
11     top_error: &'a (dyn Error + 'static),
12     component: &str,
13     // Function optionally returning the display representation of an error.
14     display_modifier: impl Fn(
15         /* level */ usize,
16         /*indention */ usize,
17         &'a (dyn Error + 'static),
18     ) -> Option<String>,
19 ) {
20     eprint!("Error: {component} exited with the following ");
21     if top_error.source().is_none() {
22         eprintln!("error:");
23         eprintln!("  {top_error}");
24     } else {
25         eprintln!("chain of errors:");
26         std::iter::successors(Some(top_error), |sub_error| {
27             // Dereference necessary to mitigate rustc compiler bug.
28             // See <https://github.com/rust-lang/rust/issues/141673>
29             (*sub_error).source()
30         })
31         .enumerate()
32         .for_each(|(level, error)| {
33             // Special case: handling of HTTP Server responses in ch-remote
34             if let Some(message) = display_modifier(level, 2, error) {
35                 eprintln!("{message}");
36             } else {
37                 eprintln!("  {level}: {error}");
38             }
39         });
40     }
41 
42     eprintln!();
43     eprintln!("Debug Info: {top_error:?}");
44 }
45