Coverage Report

Created: 2025-07-12 06:22

/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
}