init_tracing_opentelemetry/
formats.rs1use tracing::Subscriber;
7use tracing_subscriber::fmt;
8use tracing_subscriber::fmt::format::FmtSpan;
9use tracing_subscriber::fmt::time::{time, uptime, Uptime};
10use tracing_subscriber::{registry::LookupSpan, Layer};
11
12use crate::config::{LogTimer, TracingConfig, WriterConfig};
13use crate::{Error, FeatureSet};
14
15pub trait LayerBuilder: Send + Sync {
17 fn build_layer<S>(
18 &self,
19 config: &TracingConfig,
20 ) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
21 where
22 S: Subscriber + for<'a> LookupSpan<'a>;
23}
24
25fn configure_layer<S, N, L, T, W>(
26 mut layer: fmt::Layer<S, N, fmt::format::Format<L, T>, W>,
27 config: &TracingConfig,
28) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
29where
30 S: Subscriber + for<'a> LookupSpan<'a>,
31 N: for<'writer> fmt::FormatFields<'writer> + Send + Sync + 'static,
32 L: Send + Sync + 'static,
33 fmt::format::Format<L, ()>: fmt::FormatEvent<S, N>,
34 fmt::format::Format<L, Uptime>: fmt::FormatEvent<S, N>,
35 fmt::format::Format<L>: fmt::FormatEvent<S, N>,
36 W: for<'writer> fmt::MakeWriter<'writer> + Send + Sync + 'static,
37{
38 let FeatureSet {
40 file_names,
41 line_numbers,
42 thread_names,
43 thread_ids,
44 timer,
45 span_events,
46 target_display,
47 } = &config.features;
48 let span_events = span_events
49 .as_ref()
50 .map_or(FmtSpan::NONE, ToOwned::to_owned);
51
52 layer = layer
54 .with_file(*file_names)
55 .with_line_number(*line_numbers)
56 .with_thread_names(*thread_names)
57 .with_thread_ids(*thread_ids)
58 .with_span_events(span_events)
59 .with_target(*target_display);
60
61 match timer {
63 LogTimer::None => configure_writer(layer.without_time(), &config.writer),
64 LogTimer::Time => configure_writer(layer.with_timer(time()), &config.writer),
65 LogTimer::Uptime => configure_writer(layer.with_timer(uptime()), &config.writer),
66 }
67}
68
69fn configure_writer<S, N, L, T, W>(
70 layer: fmt::Layer<S, N, fmt::format::Format<L, T>, W>,
71 writer: &WriterConfig,
72) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
73where
74 S: Subscriber + for<'a> LookupSpan<'a>,
75 N: for<'writer> fmt::FormatFields<'writer> + Send + Sync + 'static,
76 L: Send + Sync + 'static,
77 T: Send + Sync + 'static,
78 fmt::format::Format<L, T>: fmt::FormatEvent<S, N>,
79{
80 match writer {
81 WriterConfig::Stdout => Ok(Box::new(layer.with_writer(std::io::stdout))),
82 WriterConfig::Stderr => Ok(Box::new(layer.with_writer(std::io::stderr))),
83 WriterConfig::File(path) => {
84 let file = std::fs::OpenOptions::new()
85 .create(true)
86 .append(true)
87 .open(path)?;
88 Ok(Box::new(layer.with_writer(file)))
89 }
90 }
91}
92
93#[derive(Debug, Default, Clone)]
95pub struct PrettyLayerBuilder;
96
97impl LayerBuilder for PrettyLayerBuilder {
98 fn build_layer<S>(
99 &self,
100 config: &TracingConfig,
101 ) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
102 where
103 S: Subscriber + for<'a> LookupSpan<'a>,
104 {
105 let layer = tracing_subscriber::fmt::layer().pretty();
106
107 configure_layer(layer, config)
108 }
109}
110
111#[derive(Debug, Default, Clone)]
113pub struct JsonLayerBuilder;
114
115impl LayerBuilder for JsonLayerBuilder {
116 fn build_layer<S>(
117 &self,
118 config: &TracingConfig,
119 ) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
120 where
121 S: Subscriber + for<'a> LookupSpan<'a>,
122 {
123 let layer = tracing_subscriber::fmt::layer().json();
124
125 configure_layer(layer, config)
126 }
127}
128
129#[derive(Debug, Default, Clone)]
131pub struct FullLayerBuilder;
132
133impl LayerBuilder for FullLayerBuilder {
134 fn build_layer<S>(
135 &self,
136 config: &TracingConfig,
137 ) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
138 where
139 S: Subscriber + for<'a> LookupSpan<'a>,
140 {
141 let layer = tracing_subscriber::fmt::layer();
142
143 configure_layer(layer, config)
144 }
145}
146
147#[derive(Debug, Default, Clone)]
149pub struct CompactLayerBuilder;
150
151impl LayerBuilder for CompactLayerBuilder {
152 fn build_layer<S>(
153 &self,
154 config: &TracingConfig,
155 ) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
156 where
157 S: Subscriber + for<'a> LookupSpan<'a>,
158 {
159 let layer = tracing_subscriber::fmt::layer().compact();
160
161 configure_layer(layer, config)
162 }
163}
164
165#[cfg(feature = "logfmt")]
167#[derive(Debug, Default, Clone)]
168pub struct LogfmtLayerBuilder;
169
170#[cfg(feature = "logfmt")]
171impl LayerBuilder for LogfmtLayerBuilder {
172 fn build_layer<S>(
173 &self,
174 config: &TracingConfig,
175 ) -> Result<Box<dyn Layer<S> + Send + Sync + 'static>, Error>
176 where
177 S: Subscriber + for<'a> LookupSpan<'a>,
178 {
179 match &config.writer {
183 WriterConfig::Stderr => {
184 Ok(Box::new(tracing_logfmt::layer()))
188 }
189 _ => {
190 Ok(Box::new(tracing_logfmt::layer()))
192 }
193 }
194 }
195}