devlog_tracing/
subscriber_builder.rs

1use std::error::Error;
2
3use tracing_subscriber::fmt::{time::FormatTime, SubscriberBuilder};
4
5use crate::{
6    event_format::DevLogEventFormat, field_format::DevLogFieldFormat, time_format::DevLogTimeFormat,
7};
8
9pub struct DevLogSubscriberBuilder<TimeFormatT> {
10    field_format: DevLogFieldFormat,
11    event_format: DevLogEventFormat<TimeFormatT>,
12}
13
14impl Default for DevLogSubscriberBuilder<DevLogTimeFormat> {
15    fn default() -> Self {
16        Self {
17            field_format: DevLogFieldFormat,
18            event_format: DevLogEventFormat::default(),
19        }
20    }
21}
22
23impl<TimeFormatT> DevLogSubscriberBuilder<TimeFormatT> {
24    /// Uses the given [`FormatTime`] implementation for log time formatting.
25    pub fn with_timer<NewTimeFormatT: FormatTime>(
26        self,
27        timer: NewTimeFormatT,
28    ) -> DevLogSubscriberBuilder<NewTimeFormatT> {
29        DevLogSubscriberBuilder {
30            field_format: self.field_format,
31            event_format: DevLogEventFormat {
32                timer,
33                // We have to set every field here for the generics to work
34                display_timestamp: self.event_format.display_timestamp,
35                display_target: self.event_format.display_target,
36                display_level: self.event_format.display_level,
37                display_thread_id: self.event_format.display_thread_id,
38                display_thread_name: self.event_format.display_thread_name,
39                display_filename: self.event_format.display_filename,
40                display_line_number: self.event_format.display_line_number,
41            },
42        }
43    }
44
45    /// Excludes timestamps from log events.
46    pub fn without_time(self) -> DevLogSubscriberBuilder<()> {
47        DevLogSubscriberBuilder {
48            field_format: self.field_format,
49            event_format: DevLogEventFormat {
50                timer: (),
51                display_timestamp: false,
52                // We have to set every field here for the generics to work
53                display_target: self.event_format.display_target,
54                display_level: self.event_format.display_level,
55                display_thread_id: self.event_format.display_thread_id,
56                display_thread_name: self.event_format.display_thread_name,
57                display_filename: self.event_format.display_filename,
58                display_line_number: self.event_format.display_line_number,
59            },
60        }
61    }
62
63    /// Whether to show the target of a log event (where it originated).
64    pub fn with_target(mut self, display_target: bool) -> Self {
65        self.event_format.display_target = display_target;
66        self
67    }
68
69    /// Whether to show the level of a log event (INFO, WARN, ERROR etc.).
70    pub fn with_level(mut self, display_level: bool) -> Self {
71        self.event_format.display_level = display_level;
72        self
73    }
74
75    /// Whether to show the ID of the current thread in log events.
76    pub fn with_thread_ids(mut self, display_thread_id: bool) -> Self {
77        self.event_format.display_thread_id = display_thread_id;
78        self
79    }
80
81    /// Whether to show the name of the current thread in log events.
82    pub fn with_thread_names(mut self, display_thread_name: bool) -> Self {
83        self.event_format.display_thread_name = display_thread_name;
84        self
85    }
86
87    /// Whether to show the source code file path where a log event was logged.
88    pub fn with_file(mut self, display_filename: bool) -> Self {
89        self.event_format.display_filename = display_filename;
90        self
91    }
92
93    /// Whether to show the line number in a source code file path where a log event was logged.
94    pub fn with_line_number(mut self, display_line_number: bool) -> Self {
95        self.event_format.display_line_number = display_line_number;
96        self
97    }
98
99    /// Whether to show the source code location (file path + line number) where a log event was
100    /// logged. Equivalent to calling [`DevLogSubscriberBuilder::with_file`] and
101    /// [`DevLogSubscriberBuilder::with_line_number`] with the same value.
102    pub fn with_source_location(self, display_location: bool) -> Self {
103        self.with_line_number(display_location)
104            .with_file(display_location)
105    }
106}
107
108impl<TimeFormatT> DevLogSubscriberBuilder<TimeFormatT>
109where
110    TimeFormatT: FormatTime + Send + Sync + 'static,
111{
112    pub fn finish(self) -> impl tracing::Subscriber {
113        self.build_fmt_subscriber().finish()
114    }
115
116    pub fn try_init(self) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
117        self.build_fmt_subscriber().try_init()
118    }
119
120    pub fn init(self) {
121        self.build_fmt_subscriber().init()
122    }
123
124    fn build_fmt_subscriber(
125        self,
126    ) -> SubscriberBuilder<DevLogFieldFormat, DevLogEventFormat<TimeFormatT>> {
127        tracing_subscriber::fmt()
128            .fmt_fields(self.field_format)
129            .event_format(self.event_format)
130    }
131}