snarkos_cli/helpers/
logger.rs

1// Copyright 2024 Aleo Network Foundation
2// This file is part of the snarkOS library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use crate::helpers::{DynamicFormatter, LogWriter};
17
18use crossterm::tty::IsTty;
19use std::{
20    fs::File,
21    io,
22    path::Path,
23    sync::{Arc, atomic::AtomicBool},
24};
25use tokio::sync::mpsc;
26use tracing_subscriber::{
27    EnvFilter,
28    layer::{Layer, SubscriberExt},
29    util::SubscriberInitExt,
30};
31
32/// Initializes the logger.
33///
34/// ```ignore
35/// 0 => info
36/// 1 => info, debug
37/// 2 => info, debug, trace, snarkos_node_sync=trace
38/// 3 => info, debug, trace, snarkos_node_bft=trace
39/// 4 => info, debug, trace, snarkos_node_bft::gateway=trace
40/// 5 => info, debug, trace, snarkos_node_router=trace
41/// 6 => info, debug, trace, snarkos_node_tcp=trace
42/// ```
43pub fn initialize_logger<P: AsRef<Path>>(
44    verbosity: u8,
45    nodisplay: bool,
46    logfile: P,
47    shutdown: Arc<AtomicBool>,
48) -> mpsc::Receiver<Vec<u8>> {
49    match verbosity {
50        0 => std::env::set_var("RUST_LOG", "info"),
51        1 => std::env::set_var("RUST_LOG", "debug"),
52        2.. => std::env::set_var("RUST_LOG", "trace"),
53    };
54
55    // Filter out undesirable logs. (unfortunately EnvFilter cannot be cloned)
56    let [filter, filter2] = std::array::from_fn(|_| {
57        let filter = EnvFilter::from_default_env()
58            .add_directive("mio=off".parse().unwrap())
59            .add_directive("tokio_util=off".parse().unwrap())
60            .add_directive("hyper=off".parse().unwrap())
61            .add_directive("reqwest=off".parse().unwrap())
62            .add_directive("want=off".parse().unwrap())
63            .add_directive("warp=off".parse().unwrap());
64
65        let filter = if verbosity >= 2 {
66            filter.add_directive("snarkos_node_sync=trace".parse().unwrap())
67        } else {
68            filter.add_directive("snarkos_node_sync=debug".parse().unwrap())
69        };
70
71        let filter = if verbosity >= 3 {
72            filter
73                .add_directive("snarkos_node_bft=trace".parse().unwrap())
74                .add_directive("snarkos_node_bft::gateway=debug".parse().unwrap())
75        } else {
76            filter.add_directive("snarkos_node_bft=debug".parse().unwrap())
77        };
78
79        let filter = if verbosity >= 4 {
80            filter.add_directive("snarkos_node_bft::gateway=trace".parse().unwrap())
81        } else {
82            filter.add_directive("snarkos_node_bft::gateway=debug".parse().unwrap())
83        };
84
85        let filter = if verbosity >= 5 {
86            filter.add_directive("snarkos_node_router=trace".parse().unwrap())
87        } else {
88            filter.add_directive("snarkos_node_router=debug".parse().unwrap())
89        };
90
91        if verbosity >= 6 {
92            filter.add_directive("snarkos_node_tcp=trace".parse().unwrap())
93        } else {
94            filter.add_directive("snarkos_node_tcp=off".parse().unwrap())
95        }
96    });
97
98    // Create the directories tree for a logfile if it doesn't exist.
99    let logfile_dir = logfile.as_ref().parent().expect("Root directory passed as a logfile");
100    if !logfile_dir.exists() {
101        std::fs::create_dir_all(logfile_dir)
102            .expect("Failed to create a directories: '{logfile_dir}', please check if user has permissions");
103    }
104    // Create a file to write logs to.
105    let logfile =
106        File::options().append(true).create(true).open(logfile).expect("Failed to open the file for writing logs");
107
108    // Initialize the log channel.
109    let (log_sender, log_receiver) = mpsc::channel(1024);
110
111    // Initialize the log sender.
112    let log_sender = match nodisplay {
113        true => None,
114        false => Some(log_sender),
115    };
116
117    // Initialize tracing.
118    let _ = tracing_subscriber::registry()
119        .with(
120            // Add layer using LogWriter for stdout / terminal
121            tracing_subscriber::fmt::Layer::default()
122                .with_ansi(log_sender.is_none() && io::stdout().is_tty())
123                .with_writer(move || LogWriter::new(&log_sender))
124                .with_target(verbosity > 2)
125                .event_format(DynamicFormatter::new(shutdown))
126                .with_filter(filter),
127        )
128        .with(
129            // Add layer redirecting logs to the file
130            tracing_subscriber::fmt::Layer::default()
131                .with_ansi(false)
132                .with_writer(logfile)
133                .with_target(verbosity > 2)
134                .with_filter(filter2),
135        )
136        .try_init();
137
138    log_receiver
139}
140
141/// Returns the welcome message as a string.
142pub fn welcome_message() -> String {
143    use colored::Colorize;
144
145    let mut output = String::new();
146    output += &r#"
147
148         ╦╬╬╬╬╬╦
149        ╬╬╬╬╬╬╬╬╬                    ▄▄▄▄        ▄▄▄
150       ╬╬╬╬╬╬╬╬╬╬╬                  ▐▓▓▓▓▌       ▓▓▓
151      ╬╬╬╬╬╬╬╬╬╬╬╬╬                ▐▓▓▓▓▓▓▌      ▓▓▓     ▄▄▄▄▄▄       ▄▄▄▄▄▄
152     ╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬              ▐▓▓▓  ▓▓▓▌     ▓▓▓   ▄▓▓▀▀▀▀▓▓▄   ▐▓▓▓▓▓▓▓▓▌
153    ╬╬╬╬╬╬╬╜ ╙╬╬╬╬╬╬╬            ▐▓▓▓▌  ▐▓▓▓▌    ▓▓▓  ▐▓▓▓▄▄▄▄▓▓▓▌ ▐▓▓▓    ▓▓▓▌
154   ╬╬╬╬╬╬╣     ╠╬╬╬╬╬╬           ▓▓▓▓▓▓▓▓▓▓▓▓    ▓▓▓  ▐▓▓▀▀▀▀▀▀▀▀▘ ▐▓▓▓    ▓▓▓▌
155  ╬╬╬╬╬╬╣       ╠╬╬╬╬╬╬         ▓▓▓▓▌    ▐▓▓▓▓   ▓▓▓   ▀▓▓▄▄▄▄▓▓▀   ▐▓▓▓▓▓▓▓▓▌
156 ╬╬╬╬╬╬╣         ╠╬╬╬╬╬╬       ▝▀▀▀▀      ▀▀▀▀▘  ▀▀▀     ▀▀▀▀▀▀       ▀▀▀▀▀▀
157╚╬╬╬╬╬╩           ╩╬╬╬╬╩
158
159
160"#
161    .white()
162    .bold();
163    output += &"👋 Welcome to Aleo! We thank you for running a node and supporting privacy.\n".bold();
164    output
165}