node_launchpad/
utils.rs

1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use crate::config::get_launchpad_data_dir_path;
10use color_eyre::eyre::{Context, Result};
11use tracing::error;
12use tracing_error::ErrorLayer;
13use tracing_subscriber::{
14    self, prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt, Layer,
15};
16
17pub fn initialize_panic_handler() -> Result<()> {
18    let (panic_hook, eyre_hook) = color_eyre::config::HookBuilder::default()
19        .panic_section(format!(
20            "This is a bug. Consider reporting it at {}",
21            env!("CARGO_PKG_REPOSITORY")
22        ))
23        .capture_span_trace_by_default(false)
24        .display_location_section(false)
25        .display_env_section(false)
26        .into_hooks();
27    eyre_hook.install()?;
28    std::panic::set_hook(Box::new(move |panic_info| {
29        if let Ok(mut t) = crate::tui::Tui::new() {
30            if let Err(r) = t.exit() {
31                error!("Unable to exit Terminal: {:?}", r);
32            }
33        }
34
35        #[cfg(not(debug_assertions))]
36        {
37            use human_panic::{handle_dump, print_msg, Metadata};
38            let meta = Metadata {
39                version: env!("CARGO_PKG_VERSION").into(),
40                name: env!("CARGO_PKG_NAME").into(),
41                authors: env!("CARGO_PKG_AUTHORS").replace(':', ", ").into(),
42                homepage: "https://autonomi.com/".into(),
43            };
44
45            let file_path = handle_dump(&meta, panic_info);
46            // prints human-panic message
47            print_msg(file_path, &meta)
48                .expect("human-panic: printing error message to console failed");
49            eprintln!("{}", panic_hook.panic_report(panic_info)); // prints color-eyre stack trace to stderr
50        }
51        let msg = format!("{}", panic_hook.panic_report(panic_info));
52        log::error!("Error: {}", strip_ansi_escapes::strip_str(msg));
53
54        #[cfg(debug_assertions)]
55        {
56            // Better Panic stacktrace that is only enabled when debugging.
57            better_panic::Settings::auto()
58                .most_recent_first(false)
59                .lineno_suffix(true)
60                .verbosity(better_panic::Verbosity::Full)
61                .create_panic_handler()(panic_info);
62        }
63
64        std::process::exit(libc::EXIT_FAILURE);
65    }));
66    Ok(())
67}
68
69// Gets the current logging path
70pub fn get_logging_path() -> Result<std::path::PathBuf> {
71    let log_path = get_launchpad_data_dir_path()?.join("logs");
72    Ok(log_path)
73}
74
75// TODO: use ant_logging
76pub fn initialize_logging() -> Result<()> {
77    let timestamp = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S").to_string();
78    let log_path = get_logging_path()?;
79    std::fs::create_dir_all(&log_path)?;
80    let log_file = std::fs::File::create(log_path.join(format!("launchpad_{timestamp}.log")))
81        .context(format!("Failed to create file {log_path:?}"))?;
82    std::env::set_var(
83        "RUST_LOG",
84        std::env::var("RUST_LOG").unwrap_or_else(|_| {
85            format!(
86                "{}=trace,ant_node_manager=trace,ant_service_management=trace,ant_bootstrap=debug",
87                env!("CARGO_CRATE_NAME")
88            )
89        }),
90    );
91    let file_subscriber = tracing_subscriber::fmt::layer()
92        .with_file(true)
93        .with_line_number(true)
94        .with_writer(log_file)
95        .with_target(false)
96        .with_ansi(false)
97        .with_filter(tracing_subscriber::filter::EnvFilter::from_default_env());
98    tracing_subscriber::registry()
99        .with(file_subscriber)
100        .with(ErrorLayer::default())
101        .init();
102    Ok(())
103}
104
105/// Similar to the `std::dbg!` macro, but generates `tracing` events rather
106/// than printing to stdout.
107///
108/// By default, the verbosity level for the generated events is `DEBUG`, but
109/// this can be customized.
110#[macro_export]
111macro_rules! trace_dbg {
112    (target: $target:expr, level: $level:expr, $ex:expr) => {{
113        match $ex {
114            value => {
115                tracing::event!(target: $target, $level, ?value, stringify!($ex));
116                value
117            }
118        }
119    }};
120    (level: $level:expr, $ex:expr) => {
121        trace_dbg!(target: module_path!(), level: $level, $ex)
122    };
123    (target: $target:expr, $ex:expr) => {
124        trace_dbg!(target: $target, level: tracing::Level::DEBUG, $ex)
125    };
126    ($ex:expr) => {
127        trace_dbg!(level: tracing::Level::DEBUG, $ex)
128    };
129}