scsys_config/services/logger/
tracing.rs

1/*
2    Appellation: tracing <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5
6#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
7#[cfg_attr(
8    feature = "serde",
9    derive(serde::Deserialize, serde::Serialize),
10    serde(default, rename_all = "snake_case")
11)]
12pub struct TracingConfig {
13    pub(crate) ansi: bool,
14    pub(crate) file: bool,
15    pub(crate) line_number: bool,
16    pub(crate) target: bool,
17    pub(crate) timer: bool,
18    pub(crate) thread_ids: bool,
19    pub(crate) thread_names: bool,
20}
21
22impl TracingConfig {
23    pub fn new() -> Self {
24        Self {
25            ansi: true,
26            file: false,
27            line_number: false,
28            target: true,
29            timer: true,
30            thread_ids: false,
31            thread_names: false,
32        }
33    }
34    /// Set the ansi toggle
35    pub fn ansi(self, ansi: bool) -> Self {
36        Self { ansi, ..self }
37    }
38    /// toggle if the ansi colors should be used in the tracing output; (default: false)
39    pub fn file(self, file: bool) -> Self {
40        Self { file, ..self }
41    }
42    /// toggle if the file name should be included in the tracing output; (default: false)
43    pub fn line_number(self, line_number: bool) -> Self {
44        Self {
45            line_number,
46            ..self
47        }
48    }
49    /// toggle if the target should be included in the tracing output; (default: true)
50    pub fn target(self, target: bool) -> Self {
51        Self { target, ..self }
52    }
53    /// toggle if the timer should be included in the tracing output; (default: true)
54    pub fn timer(self, timer: bool) -> Self {
55        Self { timer, ..self }
56    }
57    /// toggle if the thread ids should be included in the tracing output; (default: false)
58    pub fn thread_ids(self, thread_ids: bool) -> Self {
59        Self { thread_ids, ..self }
60    }
61    /// toggle if the thread names should be included in the tracing output; (default: false)
62    pub fn thread_names(self, thread_names: bool) -> Self {
63        Self {
64            thread_names,
65            ..self
66        }
67    }
68
69    pub fn get(&self, name: &str) -> bool {
70        match name {
71            "ansi" => self.ansi,
72            "file" => self.file,
73            "line_number" => self.line_number,
74            "target" => self.target,
75            "timer" => self.timer,
76            "thread_ids" => self.thread_ids,
77            "thread_names" => self.thread_names,
78            _ => panic!("unknown tracing config option"),
79        }
80    }
81    /// returns true if the ansi toggle is set
82    pub const fn get_ansi(&self) -> bool {
83        self.ansi
84    }
85    /// returns true if the file toggle is set
86    pub const fn get_file(&self) -> bool {
87        self.file
88    }
89    /// returns true if the line number is toggled
90    pub const fn get_line_number(&self) -> bool {
91        self.line_number
92    }
93    /// returns true if the target is toggled
94    pub const fn get_target(&self) -> bool {
95        self.target
96    }
97    /// returns true if the thread ids are toggled
98    pub const fn get_thread_ids(&self) -> bool {
99        self.thread_ids
100    }
101    /// returns true if the thread names are toggled
102    pub const fn get_thread_names(&self) -> bool {
103        self.thread_names
104    }
105
106    #[cfg(feature = "tracing-subscriber")]
107    /// Initialize the tracer with the given name
108    pub fn init_tracing(self, level: crate::LogLevel, name: Option<&str>) -> Self {
109        use tracing_subscriber::{filter::EnvFilter, util::SubscriberInitExt};
110        let name = name.unwrap_or(env!("CARGO_PKG_NAME"));
111        let filter = EnvFilter::try_from_default_env()
112            .unwrap_or_else(|_| format!("{name}={level},tower_http={level}").into());
113        // deconstruct the config
114        let Self {
115            ansi,
116            file,
117            line_number,
118            target,
119            thread_ids,
120            thread_names,
121            ..
122        } = self;
123        // initialize the tracing subscriber
124        tracing_subscriber::fmt()
125            .compact()
126            .with_ansi(ansi)
127            .with_env_filter(filter)
128            .with_file(file)
129            .with_line_number(line_number)
130            .with_max_level(level.as_tracing_level())
131            .with_target(target)
132            .with_thread_ids(thread_ids)
133            .with_thread_names(thread_names)
134            .with_timer(tracing_subscriber::fmt::time::uptime())
135            .finish()
136            .init();
137        // trace the success
138        tracing::trace!("successfully initialized the tracing subscriber");
139        self
140    }
141}
142
143impl Default for TracingConfig {
144    fn default() -> Self {
145        Self::new()
146    }
147}
148
149impl core::fmt::Display for TracingConfig {
150    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
151        #[cfg(feature = "json")]
152        {
153            f.write_str(&serde_json::to_string(self).unwrap())
154        }
155        #[cfg(not(feature = "json"))]
156        {
157            write!(
158                f,
159                "{{ ansi: {}, file: {}, line_number: {}, target: {}, timer: {}, thread_ids: {}, thread_names: {} }}",
160                self.ansi,
161                self.file,
162                self.line_number,
163                self.target,
164                self.timer,
165                self.thread_ids,
166                self.thread_names
167            )
168        }
169    }
170}