/rust/registry/src/index.crates.io-6f17d22bba15001f/tracing-subscriber-0.3.19/src/field/mod.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! Utilities for working with [fields] and [field visitors]. |
2 | | //! |
3 | | //! [fields]: tracing_core::field |
4 | | //! [field visitors]: tracing_core::field::Visit |
5 | | use core::{fmt, marker::PhantomData}; |
6 | | pub use tracing_core::field::Visit; |
7 | | use tracing_core::{ |
8 | | span::{Attributes, Record}, |
9 | | Event, |
10 | | }; |
11 | | pub mod debug; |
12 | | pub mod delimited; |
13 | | pub mod display; |
14 | | |
15 | | /// Creates new [visitors]. |
16 | | /// |
17 | | /// A type implementing `MakeVisitor` represents a composable factory for types |
18 | | /// implementing the [`Visit` trait][visitors]. The `MakeVisitor` trait defines |
19 | | /// a single function, `make_visitor`, which takes in a `T`-typed `target` and |
20 | | /// returns a type implementing `Visit` configured for that target. A target may |
21 | | /// be a string, output stream, or data structure that the visitor will record |
22 | | /// data to, configuration variables that determine the visitor's behavior, or |
23 | | /// `()` when no input is required to produce a visitor. |
24 | | /// |
25 | | /// [visitors]: tracing_core::field::Visit |
26 | | pub trait MakeVisitor<T> { |
27 | | /// The visitor type produced by this `MakeVisitor`. |
28 | | type Visitor: Visit; |
29 | | |
30 | | /// Make a new visitor for the provided `target`. |
31 | | fn make_visitor(&self, target: T) -> Self::Visitor; |
32 | | } |
33 | | |
34 | | /// A [visitor] that produces output once it has visited a set of fields. |
35 | | /// |
36 | | /// [visitor]: tracing_core::field::Visit |
37 | | pub trait VisitOutput<Out>: Visit { |
38 | | /// Completes the visitor, returning any output. |
39 | | /// |
40 | | /// This is called once a full set of fields has been visited. |
41 | | fn finish(self) -> Out; |
42 | | |
43 | | /// Visit a set of fields, and return the output of finishing the visitor |
44 | | /// once the fields have been visited. |
45 | 0 | fn visit<R>(mut self, fields: &R) -> Out |
46 | 0 | where |
47 | 0 | R: RecordFields, |
48 | 0 | Self: Sized, |
49 | 0 | { |
50 | 0 | fields.record(&mut self); |
51 | 0 | self.finish() |
52 | 0 | } |
53 | | } |
54 | | |
55 | | /// Extension trait implemented by types which can be recorded by a [visitor]. |
56 | | /// |
57 | | /// This allows writing code that is generic over `tracing_core`'s |
58 | | /// [`span::Attributes`][attr], [`span::Record`][rec], and [`Event`] |
59 | | /// types. These types all provide inherent `record` methods that allow a |
60 | | /// visitor to record their fields, but there is no common trait representing this. |
61 | | /// |
62 | | /// With `RecordFields`, we can write code like this: |
63 | | /// ``` |
64 | | /// use tracing_core::field::Visit; |
65 | | /// # use tracing_core::field::Field; |
66 | | /// use tracing_subscriber::field::RecordFields; |
67 | | /// |
68 | | /// struct MyVisitor { |
69 | | /// // ... |
70 | | /// } |
71 | | /// # impl MyVisitor { fn new() -> Self { Self{} } } |
72 | | /// impl Visit for MyVisitor { |
73 | | /// // ... |
74 | | /// # fn record_debug(&mut self, _: &Field, _: &dyn std::fmt::Debug) {} |
75 | | /// } |
76 | | /// |
77 | | /// fn record_with_my_visitor<R>(r: R) |
78 | | /// where |
79 | | /// R: RecordFields, |
80 | | /// { |
81 | | /// let mut visitor = MyVisitor::new(); |
82 | | /// r.record(&mut visitor); |
83 | | /// } |
84 | | /// ``` |
85 | | /// [visitor]: tracing_core::field::Visit |
86 | | /// [attr]: tracing_core::span::Attributes |
87 | | /// [rec]: tracing_core::span::Record |
88 | | pub trait RecordFields: crate::sealed::Sealed<RecordFieldsMarker> { |
89 | | /// Record all the fields in `self` with the provided `visitor`. |
90 | | fn record(&self, visitor: &mut dyn Visit); |
91 | | } |
92 | | |
93 | | /// Extension trait implemented for all `MakeVisitor` implementations that |
94 | | /// produce a visitor implementing `VisitOutput`. |
95 | | pub trait MakeOutput<T, Out> |
96 | | where |
97 | | Self: MakeVisitor<T> + crate::sealed::Sealed<(T, Out)>, |
98 | | Self::Visitor: VisitOutput<Out>, |
99 | | { |
100 | | /// Visits all fields in `fields` with a new visitor constructed from |
101 | | /// `target`. |
102 | 0 | fn visit_with<F>(&self, target: T, fields: &F) -> Out |
103 | 0 | where |
104 | 0 | F: RecordFields, |
105 | 0 | { |
106 | 0 | self.make_visitor(target).visit(fields) |
107 | 0 | } |
108 | | } |
109 | | |
110 | | feature! { |
111 | | #![feature = "std"] |
112 | | use std::io; |
113 | | |
114 | | /// Extension trait implemented by visitors to indicate that they write to an |
115 | | /// `io::Write` instance, and allow access to that writer. |
116 | | pub trait VisitWrite: VisitOutput<Result<(), io::Error>> { |
117 | | /// Returns the writer that this visitor writes to. |
118 | | fn writer(&mut self) -> &mut dyn io::Write; |
119 | | } |
120 | | } |
121 | | |
122 | | /// Extension trait implemented by visitors to indicate that they write to a |
123 | | /// `fmt::Write` instance, and allow access to that writer. |
124 | | pub trait VisitFmt: VisitOutput<fmt::Result> { |
125 | | /// Returns the formatter that this visitor writes to. |
126 | | fn writer(&mut self) -> &mut dyn fmt::Write; |
127 | | } |
128 | | |
129 | | /// Extension trait providing `MakeVisitor` combinators. |
130 | | pub trait MakeExt<T> |
131 | | where |
132 | | Self: MakeVisitor<T> + Sized, |
133 | | Self: crate::sealed::Sealed<MakeExtMarker<T>>, |
134 | | { |
135 | | /// Wraps `self` so that any `fmt::Debug` fields are recorded using the |
136 | | /// alternate formatter (`{:#?}`). |
137 | 0 | fn debug_alt(self) -> debug::Alt<Self> { |
138 | 0 | debug::Alt::new(self) |
139 | 0 | } |
140 | | |
141 | | /// Wraps `self` so that any string fields named "message" are recorded |
142 | | /// using `fmt::Display`. |
143 | 0 | fn display_messages(self) -> display::Messages<Self> { |
144 | 0 | display::Messages::new(self) |
145 | 0 | } |
146 | | |
147 | | /// Wraps `self` so that when fields are formatted to a writer, they are |
148 | | /// separated by the provided `delimiter`. |
149 | 0 | fn delimited<D>(self, delimiter: D) -> delimited::Delimited<D, Self> |
150 | 0 | where |
151 | 0 | D: AsRef<str> + Clone, |
152 | 0 | Self::Visitor: VisitFmt, |
153 | 0 | { |
154 | 0 | delimited::Delimited::new(delimiter, self) |
155 | 0 | } |
156 | | } |
157 | | |
158 | | // === impl RecordFields === |
159 | | |
160 | | impl crate::sealed::Sealed<RecordFieldsMarker> for Event<'_> {} |
161 | | impl RecordFields for Event<'_> { |
162 | 0 | fn record(&self, visitor: &mut dyn Visit) { |
163 | 0 | Event::record(self, visitor) |
164 | 0 | } |
165 | | } |
166 | | |
167 | | impl crate::sealed::Sealed<RecordFieldsMarker> for Attributes<'_> {} |
168 | | impl RecordFields for Attributes<'_> { |
169 | 0 | fn record(&self, visitor: &mut dyn Visit) { |
170 | 0 | Attributes::record(self, visitor) |
171 | 0 | } |
172 | | } |
173 | | |
174 | | impl crate::sealed::Sealed<RecordFieldsMarker> for Record<'_> {} |
175 | | impl RecordFields for Record<'_> { |
176 | 0 | fn record(&self, visitor: &mut dyn Visit) { |
177 | 0 | Record::record(self, visitor) |
178 | 0 | } |
179 | | } |
180 | | |
181 | | impl<F> crate::sealed::Sealed<RecordFieldsMarker> for &F where F: RecordFields {} |
182 | | impl<F> RecordFields for &F |
183 | | where |
184 | | F: RecordFields, |
185 | | { |
186 | 0 | fn record(&self, visitor: &mut dyn Visit) { |
187 | 0 | F::record(*self, visitor) |
188 | 0 | } Unexecuted instantiation: <&tracing_core::span::Attributes as tracing_subscriber::field::RecordFields>::record Unexecuted instantiation: <&tracing_core::span::Record as tracing_subscriber::field::RecordFields>::record Unexecuted instantiation: <&tracing_core::event::Event as tracing_subscriber::field::RecordFields>::record |
189 | | } |
190 | | |
191 | | // === blanket impls === |
192 | | |
193 | | impl<T, V, F> MakeVisitor<T> for F |
194 | | where |
195 | | F: Fn(T) -> V, |
196 | | V: Visit, |
197 | | { |
198 | | type Visitor = V; |
199 | 0 | fn make_visitor(&self, target: T) -> Self::Visitor { |
200 | 0 | (self)(target) |
201 | 0 | } |
202 | | } |
203 | | |
204 | | impl<T, Out, M> crate::sealed::Sealed<(T, Out)> for M |
205 | | where |
206 | | M: MakeVisitor<T>, |
207 | | M::Visitor: VisitOutput<Out>, |
208 | | { |
209 | | } |
210 | | |
211 | | impl<T, Out, M> MakeOutput<T, Out> for M |
212 | | where |
213 | | M: MakeVisitor<T>, |
214 | | M::Visitor: VisitOutput<Out>, |
215 | | { |
216 | | } |
217 | | |
218 | | impl<T, M> crate::sealed::Sealed<MakeExtMarker<T>> for M where M: MakeVisitor<T> + Sized {} |
219 | | |
220 | | impl<T, M> MakeExt<T> for M |
221 | | where |
222 | | M: MakeVisitor<T> + Sized, |
223 | | M: crate::sealed::Sealed<MakeExtMarker<T>>, |
224 | | { |
225 | | } |
226 | | |
227 | | #[derive(Debug)] |
228 | | #[doc(hidden)] |
229 | | pub struct MakeExtMarker<T> { |
230 | | _p: PhantomData<T>, |
231 | | } |
232 | | |
233 | | #[derive(Debug)] |
234 | | #[doc(hidden)] |
235 | | pub struct RecordFieldsMarker { |
236 | | _p: (), |
237 | | } |
238 | | |
239 | | #[cfg(all(test, feature = "alloc"))] |
240 | | #[macro_use] |
241 | | pub(in crate::field) mod test_util { |
242 | | use super::*; |
243 | | pub(in crate::field) use alloc::string::String; |
244 | | use tracing_core::{ |
245 | | callsite::Callsite, |
246 | | field::{Field, Value}, |
247 | | metadata::{Kind, Level, Metadata}, |
248 | | }; |
249 | | |
250 | | pub(crate) struct TestAttrs1; |
251 | | pub(crate) struct TestAttrs2; |
252 | | |
253 | | impl TestAttrs1 { |
254 | | pub(crate) fn with<T>(f: impl FnOnce(Attributes<'_>) -> T) -> T { |
255 | | let fieldset = TEST_META_1.fields(); |
256 | | let values = &[ |
257 | | ( |
258 | | &fieldset.field("question").unwrap(), |
259 | | Some(&"life, the universe, and everything" as &dyn Value), |
260 | | ), |
261 | | (&fieldset.field("question.answer").unwrap(), None), |
262 | | ( |
263 | | &fieldset.field("tricky").unwrap(), |
264 | | Some(&true as &dyn Value), |
265 | | ), |
266 | | ( |
267 | | &fieldset.field("can_you_do_it").unwrap(), |
268 | | Some(&true as &dyn Value), |
269 | | ), |
270 | | ]; |
271 | | let valueset = fieldset.value_set(values); |
272 | | let attrs = tracing_core::span::Attributes::new(&TEST_META_1, &valueset); |
273 | | f(attrs) |
274 | | } |
275 | | } |
276 | | |
277 | | impl TestAttrs2 { |
278 | | pub(crate) fn with<T>(f: impl FnOnce(Attributes<'_>) -> T) -> T { |
279 | | let fieldset = TEST_META_1.fields(); |
280 | | let none = tracing_core::field::debug(&Option::<&str>::None); |
281 | | let values = &[ |
282 | | ( |
283 | | &fieldset.field("question").unwrap(), |
284 | | Some(&none as &dyn Value), |
285 | | ), |
286 | | ( |
287 | | &fieldset.field("question.answer").unwrap(), |
288 | | Some(&42 as &dyn Value), |
289 | | ), |
290 | | ( |
291 | | &fieldset.field("tricky").unwrap(), |
292 | | Some(&true as &dyn Value), |
293 | | ), |
294 | | ( |
295 | | &fieldset.field("can_you_do_it").unwrap(), |
296 | | Some(&false as &dyn Value), |
297 | | ), |
298 | | ]; |
299 | | let valueset = fieldset.value_set(values); |
300 | | let attrs = tracing_core::span::Attributes::new(&TEST_META_1, &valueset); |
301 | | f(attrs) |
302 | | } |
303 | | } |
304 | | |
305 | | struct TestCallsite1; |
306 | | static TEST_CALLSITE_1: &'static dyn Callsite = &TestCallsite1; |
307 | | static TEST_META_1: Metadata<'static> = tracing_core::metadata! { |
308 | | name: "field_test1", |
309 | | target: module_path!(), |
310 | | level: Level::INFO, |
311 | | fields: &["question", "question.answer", "tricky", "can_you_do_it"], |
312 | | callsite: TEST_CALLSITE_1, |
313 | | kind: Kind::SPAN, |
314 | | }; |
315 | | |
316 | | impl Callsite for TestCallsite1 { |
317 | | fn set_interest(&self, _: tracing_core::subscriber::Interest) { |
318 | | unimplemented!() |
319 | | } |
320 | | |
321 | | fn metadata(&self) -> &Metadata<'_> { |
322 | | &TEST_META_1 |
323 | | } |
324 | | } |
325 | | |
326 | | pub(crate) struct MakeDebug; |
327 | | pub(crate) struct DebugVisitor<'a> { |
328 | | writer: &'a mut dyn fmt::Write, |
329 | | err: fmt::Result, |
330 | | } |
331 | | |
332 | | impl<'a> DebugVisitor<'a> { |
333 | | pub(crate) fn new(writer: &'a mut dyn fmt::Write) -> Self { |
334 | | Self { |
335 | | writer, |
336 | | err: Ok(()), |
337 | | } |
338 | | } |
339 | | } |
340 | | |
341 | | impl Visit for DebugVisitor<'_> { |
342 | | fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { |
343 | | write!(self.writer, "{}={:?}", field, value).unwrap(); |
344 | | } |
345 | | } |
346 | | |
347 | | impl VisitOutput<fmt::Result> for DebugVisitor<'_> { |
348 | | fn finish(self) -> fmt::Result { |
349 | | self.err |
350 | | } |
351 | | } |
352 | | |
353 | | impl VisitFmt for DebugVisitor<'_> { |
354 | | fn writer(&mut self) -> &mut dyn fmt::Write { |
355 | | self.writer |
356 | | } |
357 | | } |
358 | | |
359 | | impl<'a> MakeVisitor<&'a mut dyn fmt::Write> for MakeDebug { |
360 | | type Visitor = DebugVisitor<'a>; |
361 | | fn make_visitor(&self, w: &'a mut dyn fmt::Write) -> DebugVisitor<'a> { |
362 | | DebugVisitor::new(w) |
363 | | } |
364 | | } |
365 | | } |