xref: /cloud-hypervisor/src/lib.rs (revision 190a11f2124b0b60a2d44e85b7c9988373acfb6d)
1060c9de0SPhilipp Schuster // Copyright © 2025 Cyberus Technology GmbH
2060c9de0SPhilipp Schuster //
3060c9de0SPhilipp Schuster // SPDX-License-Identifier: Apache-2.0
46ea13270SPhilipp Schuster 
56ea13270SPhilipp Schuster use std::error::Error;
6060c9de0SPhilipp Schuster 
7060c9de0SPhilipp Schuster /// Prints a chain of errors to the user in a consistent manner.
8060c9de0SPhilipp Schuster /// The user will see a clear chain of errors, followed by debug output
9060c9de0SPhilipp Schuster /// 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*190a11f2SPhilipp Schuster pub fn cli_print_error_chain<'a>(
11*190a11f2SPhilipp Schuster     top_error: &'a (dyn Error + 'static),
12*190a11f2SPhilipp Schuster     component: &str,
13*190a11f2SPhilipp Schuster     // Function optionally returning the display representation of an error.
14*190a11f2SPhilipp Schuster     display_modifier: impl Fn(
15*190a11f2SPhilipp Schuster         /* level */ usize,
16*190a11f2SPhilipp Schuster         /*indention */ usize,
17*190a11f2SPhilipp Schuster         &'a (dyn Error + 'static),
18*190a11f2SPhilipp Schuster     ) -> Option<String>,
19*190a11f2SPhilipp Schuster ) {
20060c9de0SPhilipp Schuster     eprint!("Error: {component} exited with the following ");
21060c9de0SPhilipp Schuster     if top_error.source().is_none() {
22060c9de0SPhilipp Schuster         eprintln!("error:");
23060c9de0SPhilipp Schuster         eprintln!("  {top_error}");
24060c9de0SPhilipp Schuster     } else {
25060c9de0SPhilipp Schuster         eprintln!("chain of errors:");
26060c9de0SPhilipp Schuster         std::iter::successors(Some(top_error), |sub_error| {
276ea13270SPhilipp Schuster             // Dereference necessary to mitigate rustc compiler bug.
286ea13270SPhilipp Schuster             // See <https://github.com/rust-lang/rust/issues/141673>
296ea13270SPhilipp Schuster             (*sub_error).source()
30060c9de0SPhilipp Schuster         })
31060c9de0SPhilipp Schuster         .enumerate()
32060c9de0SPhilipp Schuster         .for_each(|(level, error)| {
33*190a11f2SPhilipp Schuster             // Special case: handling of HTTP Server responses in ch-remote
34*190a11f2SPhilipp Schuster             if let Some(message) = display_modifier(level, 2, error) {
35*190a11f2SPhilipp Schuster                 eprintln!("{message}");
36*190a11f2SPhilipp Schuster             } else {
37*190a11f2SPhilipp Schuster                 eprintln!("  {level}: {error}");
38*190a11f2SPhilipp Schuster             }
39060c9de0SPhilipp Schuster         });
40060c9de0SPhilipp Schuster     }
41060c9de0SPhilipp Schuster 
42060c9de0SPhilipp Schuster     eprintln!();
43060c9de0SPhilipp Schuster     eprintln!("Debug Info: {top_error:?}");
44060c9de0SPhilipp Schuster }
45