1use {
2 anstream::stderr,
3 std::{fs::*, io::*, path::*},
4 time::{format_description::*, macros::*},
5 tracing::subscriber::*,
6 tracing_subscriber::{filter::*, fmt::time::*, prelude::*, *},
7};
8
9const TIME_FORMAT: &[BorrowedFormatItem<'_>] = format_description!(
13 "[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3][offset_hour]:[offset_minute]"
14);
15
16pub fn initialize_tracing(verbosity: u8, path: Option<&PathBuf>) -> Result<()> {
27 if verbosity == 0 {
28 return Ok(());
29 }
30
31 let level = verbosity_to_level(verbosity);
32 let timer = LocalTime::new(TIME_FORMAT);
33
34 let builder = fmt().with_max_level(level).with_timer(timer);
35
36 match path {
37 Some(path) => {
38 let file = OpenOptions::new().write(true).create(true).append(true).open(path)?;
39 builder.with_writer(file).with_ansi(false).init();
40 }
41
42 None => builder.with_writer(stderr).init(),
43 };
44
45 Ok(())
46}
47
48pub fn initialize_tracing_journald(verbosity: u8) -> Result<()> {
57 if verbosity == 0 {
58 return Ok(());
59 }
60
61 let level = verbosity_to_level(verbosity);
62
63 let layer = tracing_journald::layer()?;
64 let subscriber = registry().with(LevelFilter::from_level(level)).with(layer);
65 set_global_default(subscriber).map_err(Error::other)
66}
67
68fn verbosity_to_level(verbosity: u8) -> tracing::Level {
69 match verbosity {
70 1 => tracing::Level::ERROR,
71 2 => tracing::Level::WARN,
72 3 => tracing::Level::INFO,
73 4 => tracing::Level::DEBUG,
74 _ => tracing::Level::TRACE,
75 }
76}