1use chrono::{DateTime, Utc};
7use tracing::{span, subscriber::Interest, Subscriber};
8use tracing_subscriber::registry::LookupSpan;
9
10use crate::fmt::{FmtEvent, FmtFields, FmtSpan};
11
12#[must_use = "A Layer does nothing if it is not added to a registry."]
28pub fn layer() -> Layer {
29 Layer::new()
30}
31
32pub struct Layer {}
41
42impl Layer {
43 #[must_use = "A Layer does nothing if it is not added to a registry."]
61 pub fn new() -> Self {
62 Self {}
63 }
64}
65
66impl Default for Layer {
67 #[must_use = "A Layer does nothing if it is not added to a registry."]
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl Layer {
74 #[allow(clippy::unused_self)]
76 fn write_event(&self, fmt_event: &mut FmtEvent) {
77 println!("{}", fmt_event.formatted());
78 }
79
80 fn span_event<S>(
81 &self,
82 now: DateTime<Utc>,
83 id: &span::Id,
84 ctx: &tracing_subscriber::layer::Context<'_, S>,
85 message: String,
86 ) where
87 S: Subscriber + for<'a> LookupSpan<'a>,
88 {
89 let span = ctx.span(id).expect("Span not found, this is a bug");
90 let extensions = span.extensions();
91 let Some(fmt_span) = extensions.get::<FmtSpan>() else {
92 return;
94 };
95
96 let formatted_scope = ctx
97 .span_scope(id)
98 .map(|scope| self.formatted_scope(scope))
99 .unwrap_or_default();
100 let mut fmt_event =
101 FmtEvent::new_span_event(now, fmt_span, span.metadata(), &formatted_scope, message);
102
103 self.write_event(&mut fmt_event);
104 }
105
106 #[allow(clippy::unused_self)]
108 fn formatted_scope<S>(&self, scope: tracing_subscriber::registry::Scope<'_, S>) -> String
109 where
110 S: Subscriber + for<'a> LookupSpan<'a>,
111 {
112 let mut formatted_scope = String::new();
113 for span in scope.from_root() {
114 let extensions = span.extensions();
115 let span = extensions
116 .get::<FmtSpan>()
117 .expect("cannot get fields for in-scope span. This is a bug!");
118 formatted_scope.push_str(&format!("{span} ", span = span.formatted()));
119 }
120 formatted_scope
121 }
122}
123
124impl<S> tracing_subscriber::Layer<S> for Layer
125where
126 S: Subscriber + for<'a> LookupSpan<'a>,
127{
128 fn register_callsite(&self, _metadata: &'static tracing::Metadata<'static>) -> Interest {
129 Interest::always()
130 }
131
132 fn enabled(
133 &self,
134 _metadata: &tracing::Metadata<'_>,
135 _ctx: tracing_subscriber::layer::Context<'_, S>,
136 ) -> bool {
137 true
138 }
139
140 fn on_new_span(
141 &self,
142 attrs: &span::Attributes<'_>,
143 id: &span::Id,
144 ctx: tracing_subscriber::layer::Context<'_, S>,
145 ) {
146 let now = Utc::now();
147 let span = ctx.span(id).expect("Span not found, this is a bug");
148 {
149 let mut extensions = span.extensions_mut();
150
151 if extensions.get_mut::<FmtSpan>().is_none() {
152 let mut fields = FmtFields::new_span();
153 attrs.record(&mut fields);
154 fields.format();
155 let span = FmtSpan::new(id, attrs, fields);
156 extensions.insert(span);
157 }
158 }
159
160 self.span_event(now, id, &ctx, "new".into());
161 }
162
163 fn on_event(&self, event: &tracing::Event<'_>, ctx: tracing_subscriber::layer::Context<'_, S>) {
164 let now = Utc::now();
165
166 let mut fields = FmtFields::new_event();
167 event.record(&mut fields);
168
169 let formatted_scope = ctx
170 .event_scope(event)
171 .map(|scope| self.formatted_scope(scope))
172 .unwrap_or_default();
173
174 let mut fmt_event = FmtEvent::new(now, event.metadata(), &formatted_scope, fields);
175 self.write_event(&mut fmt_event);
176 }
177
178 fn on_enter(&self, id: &span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) {
179 let now: DateTime<Utc> = Utc::now();
180 self.span_event(now, id, &ctx, "enter".into());
181 }
182
183 fn on_exit(&self, id: &span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) {
184 let now: DateTime<Utc> = Utc::now();
185 self.span_event(now, id, &ctx, "exit".into());
186 }
187
188 fn on_close(&self, id: span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) {
189 let now: DateTime<Utc> = Utc::now();
190 self.span_event(now, &id, &ctx, "close".into());
191 }
192}