dependency_injector/
logging.rs1#[cfg(feature = "logging")]
33use tracing::Level;
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
37pub enum LogFormat {
38 #[default]
40 Json,
41 Pretty,
43 Compact,
45}
46
47#[cfg(feature = "logging")]
49#[derive(Debug, Clone)]
50pub struct LoggingBuilder {
51 level: Level,
52 format: LogFormat,
53 target: Option<&'static str>,
54 with_file: bool,
55 with_line_number: bool,
56 with_thread_ids: bool,
57 with_thread_names: bool,
58}
59
60#[cfg(feature = "logging")]
61impl Default for LoggingBuilder {
62 fn default() -> Self {
63 Self {
64 level: Level::DEBUG,
65 format: LogFormat::Json,
66 target: None,
67 with_file: false,
68 with_line_number: false,
69 with_thread_ids: false,
70 with_thread_names: false,
71 }
72 }
73}
74
75#[cfg(feature = "logging")]
76impl LoggingBuilder {
77 pub fn new() -> Self {
79 Self::default()
80 }
81
82 pub fn with_level(mut self, level: Level) -> Self {
84 self.level = level;
85 self
86 }
87
88 pub fn trace(mut self) -> Self {
90 self.level = Level::TRACE;
91 self
92 }
93
94 pub fn debug(mut self) -> Self {
96 self.level = Level::DEBUG;
97 self
98 }
99
100 pub fn info(mut self) -> Self {
102 self.level = Level::INFO;
103 self
104 }
105
106 pub fn warn(mut self) -> Self {
108 self.level = Level::WARN;
109 self
110 }
111
112 pub fn error(mut self) -> Self {
114 self.level = Level::ERROR;
115 self
116 }
117
118 pub fn with_target_filter(mut self, target: &'static str) -> Self {
120 self.target = Some(target);
121 self
122 }
123
124 pub fn di_only(self) -> Self {
126 self.with_target_filter("dependency_injector")
127 }
128
129 pub fn with_file(mut self) -> Self {
131 self.with_file = true;
132 self
133 }
134
135 pub fn with_line_number(mut self) -> Self {
137 self.with_line_number = true;
138 self
139 }
140
141 pub fn with_thread_ids(mut self) -> Self {
143 self.with_thread_ids = true;
144 self
145 }
146
147 pub fn with_thread_names(mut self) -> Self {
149 self.with_thread_names = true;
150 self
151 }
152
153 pub fn json(mut self) -> Self {
155 self.format = LogFormat::Json;
156 self
157 }
158
159 pub fn pretty(mut self) -> Self {
161 self.format = LogFormat::Pretty;
162 self
163 }
164
165 pub fn compact(mut self) -> Self {
167 self.format = LogFormat::Compact;
168 self
169 }
170
171 #[cfg(any(feature = "logging-json", feature = "logging-pretty"))]
175 pub fn init(self) {
176 use tracing_subscriber::{EnvFilter, fmt, prelude::*};
177
178 let filter = if let Some(target) = self.target {
179 EnvFilter::new(format!("{}={}", target, self.level))
180 } else {
181 EnvFilter::new(self.level.to_string())
182 };
183
184 match self.format {
185 LogFormat::Json => {
186 #[cfg(feature = "logging-json")]
187 {
188 let subscriber = fmt::layer()
189 .json()
190 .with_file(self.with_file)
191 .with_line_number(self.with_line_number)
192 .with_thread_ids(self.with_thread_ids)
193 .with_thread_names(self.with_thread_names)
194 .with_target(true);
195
196 tracing_subscriber::registry()
197 .with(filter)
198 .with(subscriber)
199 .init();
200 }
201 #[cfg(not(feature = "logging-json"))]
202 {
203 let subscriber = fmt::layer()
205 .with_file(self.with_file)
206 .with_line_number(self.with_line_number)
207 .with_thread_ids(self.with_thread_ids)
208 .with_thread_names(self.with_thread_names)
209 .with_target(true);
210
211 tracing_subscriber::registry()
212 .with(filter)
213 .with(subscriber)
214 .init();
215 }
216 }
217 LogFormat::Pretty => {
218 let subscriber = fmt::layer()
219 .pretty()
220 .with_file(self.with_file)
221 .with_line_number(self.with_line_number)
222 .with_thread_ids(self.with_thread_ids)
223 .with_thread_names(self.with_thread_names)
224 .with_target(true);
225
226 tracing_subscriber::registry()
227 .with(filter)
228 .with(subscriber)
229 .init();
230 }
231 LogFormat::Compact => {
232 let subscriber = fmt::layer()
233 .compact()
234 .with_file(self.with_file)
235 .with_line_number(self.with_line_number)
236 .with_thread_ids(self.with_thread_ids)
237 .with_thread_names(self.with_thread_names)
238 .with_target(true);
239
240 tracing_subscriber::registry()
241 .with(filter)
242 .with(subscriber)
243 .init();
244 }
245 }
246 }
247
248 #[cfg(not(any(feature = "logging-json", feature = "logging-pretty")))]
250 pub fn init(self) {
251 }
254}
255
256#[cfg(feature = "logging")]
258pub fn builder() -> LoggingBuilder {
259 LoggingBuilder::new()
260}
261
262#[cfg(any(feature = "logging-json", feature = "logging-pretty"))]
267pub fn init() {
268 #[cfg(feature = "logging-json")]
269 {
270 init_json();
271 }
272 #[cfg(all(feature = "logging-pretty", not(feature = "logging-json")))]
273 {
274 init_pretty();
275 }
276}
277
278#[cfg(not(any(feature = "logging-json", feature = "logging-pretty")))]
280pub fn init() {
281 }
283
284#[cfg(any(feature = "logging-json", feature = "logging-pretty"))]
294pub fn init_json() {
295 builder().json().debug().init();
296}
297
298#[cfg(not(any(feature = "logging-json", feature = "logging-pretty")))]
300pub fn init_json() {
301 }
303
304#[cfg(any(feature = "logging-json", feature = "logging-pretty"))]
314pub fn init_pretty() {
315 builder().pretty().debug().init();
316}
317
318#[cfg(not(any(feature = "logging-json", feature = "logging-pretty")))]
320pub fn init_pretty() {
321 }
323
324#[cfg(any(feature = "logging-json", feature = "logging-pretty"))]
326pub fn init_di_only() {
327 builder().di_only().debug().init();
328}
329
330#[cfg(not(any(feature = "logging-json", feature = "logging-pretty")))]
332pub fn init_di_only() {
333 }
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339
340 #[test]
341 fn test_builder_defaults() {
342 let builder = LoggingBuilder::default();
343 assert_eq!(builder.level, Level::DEBUG);
344 assert_eq!(builder.format, LogFormat::Json);
345 assert!(builder.target.is_none());
346 }
347
348 #[test]
349 fn test_builder_chain() {
350 let builder = LoggingBuilder::new()
351 .trace()
352 .pretty()
353 .with_file()
354 .with_line_number()
355 .di_only();
356
357 assert_eq!(builder.level, Level::TRACE);
358 assert_eq!(builder.format, LogFormat::Pretty);
359 assert!(builder.with_file);
360 assert!(builder.with_line_number);
361 assert_eq!(builder.target, Some("dependency_injector"));
362 }
363}