1use crate::fail;
2use crate::printer::{PrettyPrinter, TestCapturePrinter};
3use crate::processor::{Processor, Sink};
4use crate::tag::{NoTag, Tag, TagParser};
5use crate::tree::{self, FieldSet, Tree};
6#[cfg(feature = "chrono")]
7use chrono::Utc;
8use std::fmt;
9use std::io::{self, Write};
10use std::time::Instant;
11use tracing::field::{Field, Visit};
12use tracing::span::{Attributes, Id, Record};
13use tracing::{Event, Subscriber};
14use tracing_subscriber::layer::{Context, Layer, SubscriberExt};
15use tracing_subscriber::registry::{LookupSpan, Registry, SpanRef};
16use tracing_subscriber::util::SubscriberInitExt;
17use tracing_subscriber::util::TryInitError;
18#[cfg(feature = "uuid")]
19use uuid::Uuid;
20#[cfg(feature = "uuid")]
21pub(crate) mod id;
22
23pub(crate) struct OpenedSpan {
24 span: tree::Span,
25 start: Instant,
26}
27
28impl OpenedSpan {
29 fn new<S>(attrs: &Attributes, _ctx: &Context<S>) -> Self
30 where
31 S: Subscriber + for<'a> LookupSpan<'a>,
32 {
33 let mut fields = FieldSet::default();
34 #[cfg(feature = "uuid")]
35 let mut maybe_uuid = None;
36 #[cfg(feature = "uuid")]
37 let mut defer = false;
38
39 attrs.record(&mut |field: &Field, value: &dyn fmt::Debug| {
40 #[cfg(feature = "uuid")]
41 if field.name() == "uuid" && maybe_uuid.is_none() {
42 const LENGTH: usize = 45;
43 let mut buf = [0u8; LENGTH];
44 let mut remaining = &mut buf[..];
45
46 if let Ok(()) = write!(remaining, "{value:?}") {
47 let len = LENGTH - remaining.len();
48 if let Some(parsed) = id::try_parse(&buf[..len]) {
49 maybe_uuid = Some(parsed);
50 }
51 }
52 return;
53 }
54
55 #[cfg(feature = "defer")]
56 if field.name() == "defer" {
57 defer = true;
58 return;
59 }
60
61 let value = format!("{value:?}");
62 fields.push(tree::Field::new(field.name(), value));
63 });
64
65 let shared = tree::Shared {
66 #[cfg(feature = "chrono")]
67 timestamp: Utc::now(),
68 level: *attrs.metadata().level(),
69 fields,
70 #[cfg(feature = "uuid")]
71 uuid: maybe_uuid.unwrap_or_else(|| match _ctx.lookup_current() {
72 Some(parent) => parent
73 .extensions()
74 .get::<OpenedSpan>()
75 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS)
76 .span
77 .uuid(),
78 None => Uuid::new_v4(),
79 }),
80 };
81
82 let span = tree::Span::new(shared, attrs.metadata().name());
83
84 #[cfg(feature = "defer")]
85 let span = span.defer_unless_children_attached(defer);
86
87 OpenedSpan {
88 span,
89 start: Instant::now(),
90 }
91 }
92
93 fn enter(&mut self) {
94 self.start = Instant::now();
95 }
96
97 fn exit(&mut self) {
98 self.span.total_duration += self.start.elapsed();
99 }
100
101 fn close(self) -> tree::Span {
102 self.span
103 }
104
105 fn record_event(&mut self, event: tree::Event) {
106 #[cfg(feature = "uuid")]
107 let event = {
108 let mut event = event;
109 event.shared.uuid = self.span.uuid();
110 event
111 };
112
113 self.span.nodes.push(Tree::Event(event));
114 }
115
116 fn record_span(&mut self, span: tree::Span) {
117 self.span.inner_duration += span.total_duration();
118 self.span.nodes.push(Tree::Span(span));
119 }
120
121 #[cfg(feature = "uuid")]
122 pub(crate) fn uuid(&self) -> Uuid {
123 self.span.uuid()
124 }
125}
126
127#[derive(Clone, Debug)]
130pub struct ForestLayer<P, T> {
131 processor: P,
132 tag: T,
133}
134
135impl<P: Processor, T: TagParser> ForestLayer<P, T> {
136 pub fn new(processor: P, tag: T) -> Self {
138 ForestLayer { processor, tag }
139 }
140}
141
142impl<P: Processor> From<P> for ForestLayer<P, NoTag> {
143 fn from(processor: P) -> Self {
144 ForestLayer::new(processor, NoTag)
145 }
146}
147
148impl ForestLayer<Sink, NoTag> {
149 pub fn sink() -> Self {
151 ForestLayer::from(Sink)
152 }
153}
154
155impl Default for ForestLayer<PrettyPrinter, NoTag> {
156 fn default() -> Self {
157 ForestLayer {
158 processor: PrettyPrinter::new(),
159 tag: NoTag,
160 }
161 }
162}
163
164impl<P, T, S> Layer<S> for ForestLayer<P, T>
165where
166 P: Processor,
167 T: TagParser,
168 S: Subscriber + for<'a> LookupSpan<'a>,
169{
170 fn on_new_span(&self, attrs: &Attributes, id: &Id, ctx: Context<S>) {
171 let span = ctx.span(id).expect(fail::SPAN_NOT_IN_CONTEXT);
172 let opened = OpenedSpan::new(attrs, &ctx);
173
174 if !ctx.enabled(attrs.metadata()) {
175 return;
176 }
177
178 let mut extensions = span.extensions_mut();
179 extensions.insert(opened);
180 }
181
182 fn on_record(&self, span: &Id, values: &Record<'_>, ctx: Context<'_, S>) {
183 struct Visitor<'a> {
184 fields: &'a mut FieldSet,
185 }
186
187 impl<'a> Visit for Visitor<'a> {
188 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
189 let value = format!("{:?}", value);
190 let new_field = tree::Field::new(field.name(), value);
191
192 if let Some(old_field) = self
193 .fields
194 .iter_mut()
195 .find(|old_field| old_field.key() == field.name())
196 {
197 *old_field = new_field;
198 } else {
199 self.fields.push(new_field);
200 }
201 }
202 }
203
204 let span = ctx.span(span).expect(fail::SPAN_NOT_IN_CONTEXT);
205 let mut extensions = span.extensions_mut();
206 let openedspan = extensions
207 .get_mut::<OpenedSpan>()
208 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS);
209
210 let mut visitor = Visitor {
211 fields: &mut openedspan.span.shared.fields,
212 };
213 values.record(&mut visitor);
214 }
215
216 fn on_event(&self, event: &Event, ctx: Context<S>) {
217 struct Visitor {
218 message: Option<String>,
219 fields: FieldSet,
220 immediate: bool,
221 }
222
223 impl Visit for Visitor {
224 fn record_bool(&mut self, field: &Field, value: bool) {
225 match field.name() {
226 "immediate" => self.immediate |= value,
227 _ => self.record_debug(field, &value),
228 }
229 }
230
231 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
232 let value = format!("{value:?}");
233 match field.name() {
234 "message" if self.message.is_none() => self.message = Some(value),
235 key => self.fields.push(tree::Field::new(key, value)),
236 }
237 }
238 }
239
240 let mut visitor = Visitor {
241 message: None,
242 fields: FieldSet::default(),
243 immediate: false,
244 };
245
246 event.record(&mut visitor);
247
248 let shared = tree::Shared {
249 #[cfg(feature = "uuid")]
250 uuid: Uuid::nil(),
251 #[cfg(feature = "chrono")]
252 timestamp: Utc::now(),
253 level: *event.metadata().level(),
254 fields: visitor.fields,
255 };
256
257 let tree_event = tree::Event {
258 shared,
259 message: visitor.message,
260 tag: self.tag.parse(event),
261 };
262
263 let current_span = ctx.event_span(event);
264
265 if visitor.immediate {
266 write_immediate(&tree_event, current_span.as_ref()).expect("writing urgent failed");
267 }
268
269 match current_span.as_ref() {
270 Some(parent) => parent
271 .extensions_mut()
272 .get_mut::<OpenedSpan>()
273 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS)
274 .record_event(tree_event),
275 None => self
276 .processor
277 .process(Tree::Event(tree_event))
278 .expect(fail::PROCESSING_ERROR),
279 }
280 }
281
282 fn on_enter(&self, id: &Id, ctx: Context<S>) {
283 ctx.span(id)
284 .expect(fail::SPAN_NOT_IN_CONTEXT)
285 .extensions_mut()
286 .get_mut::<OpenedSpan>()
287 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS)
288 .enter();
289 }
290
291 fn on_exit(&self, id: &Id, ctx: Context<S>) {
292 ctx.span(id)
293 .expect(fail::SPAN_NOT_IN_CONTEXT)
294 .extensions_mut()
295 .get_mut::<OpenedSpan>()
296 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS)
297 .exit();
298 }
299
300 fn on_close(&self, id: Id, ctx: Context<S>) {
301 let span_ref = ctx.span(&id).expect(fail::SPAN_NOT_IN_CONTEXT);
302
303 let mut span = span_ref
304 .extensions_mut()
305 .remove::<OpenedSpan>()
306 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS)
307 .close();
308
309 if span.total_duration < span.inner_duration {
317 span.total_duration = span.inner_duration;
318 }
319
320 match span_ref.parent() {
321 Some(parent) => parent
322 .extensions_mut()
323 .get_mut::<OpenedSpan>()
324 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS)
325 .record_span(span),
326 None => self
327 .processor
328 .process(Tree::Span(span))
329 .expect(fail::PROCESSING_ERROR),
330 }
331 }
332}
333
334fn write_immediate<S>(event: &tree::Event, current: Option<&SpanRef<S>>) -> io::Result<()>
335where
336 S: for<'a> LookupSpan<'a>,
337{
338 #[cfg(feature = "smallvec")]
340 let mut writer = smallvec::SmallVec::<[u8; 256]>::new();
341 #[cfg(not(feature = "smallvec"))]
342 let mut writer = Vec::with_capacity(256);
343
344 #[cfg(feature = "uuid")]
345 if let Some(span) = current {
346 let uuid = span
347 .extensions()
348 .get::<OpenedSpan>()
349 .expect(fail::OPENED_SPAN_NOT_IN_EXTENSIONS)
350 .span
351 .uuid();
352 write!(writer, "{uuid} ")?;
353 }
354
355 #[cfg(feature = "chrono")]
356 write!(writer, "{} ", event.timestamp().to_rfc3339())?;
357
358 write!(writer, "{:<8} ", event.level())?;
359
360 let tag = event.tag().unwrap_or_else(|| Tag::from(event.level()));
361
362 write!(writer, "{icon} IMMEDIATE {icon} ", icon = tag.icon())?;
363
364 if let Some(span) = current {
365 for ancestor in span.scope().from_root() {
366 write!(writer, "{} > ", ancestor.name())?;
367 }
368 }
369
370 if let Some(message) = event.message() {
373 write!(writer, "{message}")?;
374 }
375
376 for field in event.fields() {
377 write!(writer, " | {}: {}", field.key(), field.value())?;
378 }
379
380 writeln!(writer)?;
381
382 io::stderr().write_all(&writer)
383}
384
385pub fn init() {
412 Registry::default().with(ForestLayer::default()).init();
413}
414
415pub fn test_init() -> Result<(), TryInitError> {
435 Registry::default()
436 .with(ForestLayer::new(TestCapturePrinter::new(), NoTag))
437 .try_init()
438}