• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::any::{type_name, TypeId};
2 use std::fmt;
3 use std::marker::PhantomData;
4 use tracing::{span, Dispatch, Metadata, Subscriber};
5 use tracing_subscriber::fmt::format::{DefaultFields, FormatFields};
6 use tracing_subscriber::{
7     fmt::FormattedFields,
8     layer::{self, Layer},
9     registry::LookupSpan,
10 };
11 
12 /// A subscriber [`Layer`] that enables capturing [`SpanTrace`]s.
13 ///
14 /// Optionally, this type may be constructed with a [field formatter] to use
15 /// when formatting the fields of each span in a trace. When no formatter is
16 /// provided, the [default format] is used instead.
17 ///
18 /// [`Layer`]: tracing_subscriber::layer::Layer
19 /// [`SpanTrace`]: super::SpanTrace
20 /// [field formatter]: tracing_subscriber::fmt::FormatFields
21 /// [default format]: tracing_subscriber::fmt::format::DefaultFields
22 pub struct ErrorLayer<S, F = DefaultFields> {
23     format: F,
24 
25     get_context: WithContext,
26     _subscriber: PhantomData<fn(S)>,
27 }
28 
29 // this function "remembers" the types of the subscriber and the formatter,
30 // so that we can downcast to something aware of them without knowing those
31 // types at the callsite.
32 pub(crate) struct WithContext(
33     fn(&Dispatch, &span::Id, f: &mut dyn FnMut(&'static Metadata<'static>, &str) -> bool),
34 );
35 
36 impl<S, F> Layer<S> for ErrorLayer<S, F>
37 where
38     S: Subscriber + for<'span> LookupSpan<'span>,
39     F: for<'writer> FormatFields<'writer> + 'static,
40 {
41     /// Notifies this layer that a new span was constructed with the given
42     /// `Attributes` and `Id`.
on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>)43     fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>) {
44         let span = ctx.span(id).expect("span must already exist!");
45         if span.extensions().get::<FormattedFields<F>>().is_some() {
46             return;
47         }
48         let mut fields = FormattedFields::<F>::new(String::new());
49         if self.format.format_fields(fields.as_writer(), attrs).is_ok() {
50             span.extensions_mut().insert(fields);
51         }
52     }
53 
downcast_raw(&self, id: TypeId) -> Option<*const ()>54     unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
55         match id {
56             id if id == TypeId::of::<Self>() => Some(self as *const _ as *const ()),
57             id if id == TypeId::of::<WithContext>() => {
58                 Some(&self.get_context as *const _ as *const ())
59             }
60             _ => None,
61         }
62     }
63 }
64 
65 impl<S, F> ErrorLayer<S, F>
66 where
67     F: for<'writer> FormatFields<'writer> + 'static,
68     S: Subscriber + for<'span> LookupSpan<'span>,
69 {
70     /// Returns a new `ErrorLayer` with the provided [field formatter].
71     ///
72     /// [field formatter]: tracing_subscriber::fmt::FormatFields
new(format: F) -> Self73     pub fn new(format: F) -> Self {
74         Self {
75             format,
76             get_context: WithContext(Self::get_context),
77             _subscriber: PhantomData,
78         }
79     }
80 
get_context( dispatch: &Dispatch, id: &span::Id, f: &mut dyn FnMut(&'static Metadata<'static>, &str) -> bool, )81     fn get_context(
82         dispatch: &Dispatch,
83         id: &span::Id,
84         f: &mut dyn FnMut(&'static Metadata<'static>, &str) -> bool,
85     ) {
86         let subscriber = dispatch
87             .downcast_ref::<S>()
88             .expect("subscriber should downcast to expected type; this is a bug!");
89         let span = subscriber
90             .span(id)
91             .expect("registry should have a span for the current ID");
92         for span in span.scope() {
93             let cont = if let Some(fields) = span.extensions().get::<FormattedFields<F>>() {
94                 f(span.metadata(), fields.fields.as_str())
95             } else {
96                 f(span.metadata(), "")
97             };
98             if !cont {
99                 break;
100             }
101         }
102     }
103 }
104 
105 impl WithContext {
with_context<'a>( &self, dispatch: &'a Dispatch, id: &span::Id, mut f: impl FnMut(&'static Metadata<'static>, &str) -> bool, )106     pub(crate) fn with_context<'a>(
107         &self,
108         dispatch: &'a Dispatch,
109         id: &span::Id,
110         mut f: impl FnMut(&'static Metadata<'static>, &str) -> bool,
111     ) {
112         (self.0)(dispatch, id, &mut f)
113     }
114 }
115 
116 impl<S> Default for ErrorLayer<S>
117 where
118     S: Subscriber + for<'span> LookupSpan<'span>,
119 {
default() -> Self120     fn default() -> Self {
121         Self::new(DefaultFields::default())
122     }
123 }
124 
125 impl<S, F: fmt::Debug> fmt::Debug for ErrorLayer<S, F> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result126     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127         f.debug_struct("ErrorLayer")
128             .field("format", &self.format)
129             .field("subscriber", &format_args!("{}", type_name::<S>()))
130             .finish()
131     }
132 }
133