kutil_cli/log/
tracing.rs

1use {
2    anstream::stderr,
3    std::{fs::*, io::*, path::*},
4    time::{format_description::*, macros::format_description},
5    tracing_subscriber::{fmt::time::*, *},
6};
7
8// RFC 3339 with subseconds
9// Or ISO 8601 with fewer subsecond digits
10// See: https://time-rs.github.io/book/api/well-known-format-descriptions.html
11const TIME_FORMAT: &[BorrowedFormatItem<'_>] = format_description!(
12    "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3][offset_hour]:[offset_minute]"
13);
14
15/// Initialize a tracing subscriber for stderr.
16///
17/// * 0: no tracing subscriber.
18/// * 1: [ERROR](tracing::Level::ERROR)
19/// * 2: [WARN](tracing::Level::WARN)
20/// * 3: [INFO](tracing::Level::INFO)
21/// * 4: [DEBUG](tracing::Level::DEBUG)
22/// * >=5: [TRACE](tracing::Level::TRACE)
23pub fn initialize_tracing(verbosity: u8, path: Option<&PathBuf>) -> Result<()> {
24    if verbosity == 0 {
25        return Ok(());
26    }
27
28    let level = match verbosity {
29        1 => tracing::Level::ERROR,
30        2 => tracing::Level::WARN,
31        3 => tracing::Level::INFO,
32        4 => tracing::Level::DEBUG,
33        _ => tracing::Level::TRACE,
34    };
35
36    let timer = LocalTime::new(TIME_FORMAT);
37
38    let builder = fmt().with_max_level(level).with_timer(timer);
39
40    match path {
41        Some(path) => {
42            let file = OpenOptions::new().write(true).create(true).append(true).open(path)?;
43            builder.with_writer(file).with_ansi(false).init();
44        }
45
46        None => builder.with_writer(stderr).init(),
47    };
48
49    Ok(())
50}