tracing_error/
subscriber.rs
1use std::fmt;
2use std::marker::PhantomData;
3use std::{
4 any::{type_name, TypeId},
5 ptr::NonNull,
6};
7use tracing::{span, Collect, Dispatch, Metadata};
8use tracing_subscriber::fmt::format::{DefaultFields, FormatFields};
9use tracing_subscriber::{
10 fmt::FormattedFields,
11 registry::LookupSpan,
12 subscribe::{self, Subscribe},
13};
14
15pub struct ErrorSubscriber<C, F = DefaultFields> {
26 format: F,
27
28 get_context: WithContext,
29 _collector: PhantomData<fn(C)>,
30}
31
32pub(crate) struct WithContext(
36 fn(&Dispatch, &span::Id, f: &mut dyn FnMut(&'static Metadata<'static>, &str) -> bool),
37);
38
39impl<C, F> Subscribe<C> for ErrorSubscriber<C, F>
40where
41 C: Collect + for<'span> LookupSpan<'span>,
42 F: for<'writer> FormatFields<'writer> + 'static,
43{
44 fn on_new_span(
47 &self,
48 attrs: &span::Attributes<'_>,
49 id: &span::Id,
50 ctx: subscribe::Context<'_, C>,
51 ) {
52 let span = ctx.span(id).expect("span must already exist!");
53 if span.extensions().get::<FormattedFields<F>>().is_some() {
54 return;
55 }
56 let mut fields = FormattedFields::<F>::new(String::new());
57 if self.format.format_fields(fields.as_writer(), attrs).is_ok() {
58 span.extensions_mut().insert(fields);
59 }
60 }
61
62 unsafe fn downcast_raw(&self, id: TypeId) -> Option<NonNull<()>> {
63 match id {
64 id if id == TypeId::of::<Self>() => Some(NonNull::from(self).cast()),
65 id if id == TypeId::of::<WithContext>() => {
66 Some(NonNull::from(&self.get_context).cast())
67 }
68 _ => None,
69 }
70 }
71}
72
73impl<C, F> ErrorSubscriber<C, F>
74where
75 F: for<'writer> FormatFields<'writer> + 'static,
76 C: Collect + for<'span> LookupSpan<'span>,
77{
78 pub fn new(format: F) -> Self {
82 Self {
83 format,
84 get_context: WithContext(Self::get_context),
85 _collector: PhantomData,
86 }
87 }
88
89 fn get_context(
90 dispatch: &Dispatch,
91 id: &span::Id,
92 f: &mut dyn FnMut(&'static Metadata<'static>, &str) -> bool,
93 ) {
94 let collector = dispatch
95 .downcast_ref::<C>()
96 .expect("collector should downcast to expected type; this is a bug!");
97 let span = collector
98 .span(id)
99 .expect("registry should have a span for the current ID");
100 for span in span.scope() {
101 let cont = if let Some(fields) = span.extensions().get::<FormattedFields<F>>() {
102 f(span.metadata(), fields.fields.as_str())
103 } else {
104 f(span.metadata(), "")
105 };
106 if !cont {
107 break;
108 }
109 }
110 }
111}
112
113impl WithContext {
114 pub(crate) fn with_context(
115 &self,
116 dispatch: &Dispatch,
117 id: &span::Id,
118 mut f: impl FnMut(&'static Metadata<'static>, &str) -> bool,
119 ) {
120 (self.0)(dispatch, id, &mut f)
121 }
122}
123
124impl<C> Default for ErrorSubscriber<C>
125where
126 C: Collect + for<'span> LookupSpan<'span>,
127{
128 fn default() -> Self {
129 Self::new(DefaultFields::default())
130 }
131}
132
133impl<C, F: fmt::Debug> fmt::Debug for ErrorSubscriber<C, F> {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 f.debug_struct("ErrorSubscriber")
136 .field("format", &self.format)
137 .field("collector", &format_args!("{}", type_name::<C>()))
138 .finish()
139 }
140}