summaryrefslogtreecommitdiffstats
path: root/vendor/tracing-subscriber/src/field/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tracing-subscriber/src/field/mod.rs')
-rw-r--r--vendor/tracing-subscriber/src/field/mod.rs366
1 files changed, 366 insertions, 0 deletions
diff --git a/vendor/tracing-subscriber/src/field/mod.rs b/vendor/tracing-subscriber/src/field/mod.rs
new file mode 100644
index 000000000..5dfddb362
--- /dev/null
+++ b/vendor/tracing-subscriber/src/field/mod.rs
@@ -0,0 +1,366 @@
+//! Utilities for working with [fields] and [field visitors].
+//!
+//! [fields]: tracing_core::field
+//! [field visitors]: tracing_core::field::Visit
+use core::{fmt, marker::PhantomData};
+pub use tracing_core::field::Visit;
+use tracing_core::{
+ span::{Attributes, Record},
+ Event,
+};
+pub mod debug;
+pub mod delimited;
+pub mod display;
+
+/// Creates new [visitors].
+///
+/// A type implementing `MakeVisitor` represents a composable factory for types
+/// implementing the [`Visit` trait][visitors]. The `MakeVisitor` trait defines
+/// a single function, `make_visitor`, which takes in a `T`-typed `target` and
+/// returns a type implementing `Visit` configured for that target. A target may
+/// be a string, output stream, or data structure that the visitor will record
+/// data to, configuration variables that determine the visitor's behavior, or
+/// `()` when no input is required to produce a visitor.
+///
+/// [visitors]: tracing_core::field::Visit
+pub trait MakeVisitor<T> {
+ /// The visitor type produced by this `MakeVisitor`.
+ type Visitor: Visit;
+
+ /// Make a new visitor for the provided `target`.
+ fn make_visitor(&self, target: T) -> Self::Visitor;
+}
+
+/// A [visitor] that produces output once it has visited a set of fields.
+///
+/// [visitor]: tracing_core::field::Visit
+pub trait VisitOutput<Out>: Visit {
+ /// Completes the visitor, returning any output.
+ ///
+ /// This is called once a full set of fields has been visited.
+ fn finish(self) -> Out;
+
+ /// Visit a set of fields, and return the output of finishing the visitor
+ /// once the fields have been visited.
+ fn visit<R>(mut self, fields: &R) -> Out
+ where
+ R: RecordFields,
+ Self: Sized,
+ {
+ fields.record(&mut self);
+ self.finish()
+ }
+}
+
+/// Extension trait implemented by types which can be recorded by a [visitor].
+///
+/// This allows writing code that is generic over `tracing_core`'s
+/// [`span::Attributes`][attr], [`span::Record`][rec], and [`Event`][event]
+/// types. These types all provide inherent `record` methods that allow a
+/// visitor to record their fields, but there is no common trait representing this.
+///
+/// With `RecordFields`, we can write code like this:
+/// ```
+/// use tracing_core::field::Visit;
+/// # use tracing_core::field::Field;
+/// use tracing_subscriber::field::RecordFields;
+///
+/// struct MyVisitor {
+/// // ...
+/// }
+/// # impl MyVisitor { fn new() -> Self { Self{} } }
+/// impl Visit for MyVisitor {
+/// // ...
+/// # fn record_debug(&mut self, _: &Field, _: &dyn std::fmt::Debug) {}
+/// }
+///
+/// fn record_with_my_visitor<R>(r: R)
+/// where
+/// R: RecordFields,
+/// {
+/// let mut visitor = MyVisitor::new();
+/// r.record(&mut visitor);
+/// }
+/// ```
+/// [visitor]: tracing_core::field::Visit
+/// [attr]: tracing_core::span::Attributes
+/// [rec]: tracing_core::span::Record
+/// [event]: tracing_core::event::Event
+pub trait RecordFields: crate::sealed::Sealed<RecordFieldsMarker> {
+ /// Record all the fields in `self` with the provided `visitor`.
+ fn record(&self, visitor: &mut dyn Visit);
+}
+
+/// Extension trait implemented for all `MakeVisitor` implementations that
+/// produce a visitor implementing `VisitOutput`.
+pub trait MakeOutput<T, Out>
+where
+ Self: MakeVisitor<T> + crate::sealed::Sealed<(T, Out)>,
+ Self::Visitor: VisitOutput<Out>,
+{
+ /// Visits all fields in `fields` with a new visitor constructed from
+ /// `target`.
+ fn visit_with<F>(&self, target: T, fields: &F) -> Out
+ where
+ F: RecordFields,
+ {
+ self.make_visitor(target).visit(fields)
+ }
+}
+
+feature! {
+ #![feature = "std"]
+ use std::io;
+
+ /// Extension trait implemented by visitors to indicate that they write to an
+ /// `io::Write` instance, and allow access to that writer.
+ pub trait VisitWrite: VisitOutput<Result<(), io::Error>> {
+ /// Returns the writer that this visitor writes to.
+ fn writer(&mut self) -> &mut dyn io::Write;
+ }
+}
+
+/// Extension trait implemented by visitors to indicate that they write to a
+/// `fmt::Write` instance, and allow access to that writer.
+pub trait VisitFmt: VisitOutput<fmt::Result> {
+ /// Returns the formatter that this visitor writes to.
+ fn writer(&mut self) -> &mut dyn fmt::Write;
+}
+
+/// Extension trait providing `MakeVisitor` combinators.
+pub trait MakeExt<T>
+where
+ Self: MakeVisitor<T> + Sized,
+ Self: crate::sealed::Sealed<MakeExtMarker<T>>,
+{
+ /// Wraps `self` so that any `fmt::Debug` fields are recorded using the
+ /// alternate formatter (`{:#?}`).
+ fn debug_alt(self) -> debug::Alt<Self> {
+ debug::Alt::new(self)
+ }
+
+ /// Wraps `self` so that any string fields named "message" are recorded
+ /// using `fmt::Display`.
+ fn display_messages(self) -> display::Messages<Self> {
+ display::Messages::new(self)
+ }
+
+ /// Wraps `self` so that when fields are formatted to a writer, they are
+ /// separated by the provided `delimiter`.
+ fn delimited<D>(self, delimiter: D) -> delimited::Delimited<D, Self>
+ where
+ D: AsRef<str> + Clone,
+ Self::Visitor: VisitFmt,
+ {
+ delimited::Delimited::new(delimiter, self)
+ }
+}
+
+// === impl RecordFields ===
+
+impl<'a> crate::sealed::Sealed<RecordFieldsMarker> for Event<'a> {}
+impl<'a> RecordFields for Event<'a> {
+ fn record(&self, visitor: &mut dyn Visit) {
+ Event::record(self, visitor)
+ }
+}
+
+impl<'a> crate::sealed::Sealed<RecordFieldsMarker> for Attributes<'a> {}
+impl<'a> RecordFields for Attributes<'a> {
+ fn record(&self, visitor: &mut dyn Visit) {
+ Attributes::record(self, visitor)
+ }
+}
+
+impl<'a> crate::sealed::Sealed<RecordFieldsMarker> for Record<'a> {}
+impl<'a> RecordFields for Record<'a> {
+ fn record(&self, visitor: &mut dyn Visit) {
+ Record::record(self, visitor)
+ }
+}
+
+impl<'a, F> crate::sealed::Sealed<RecordFieldsMarker> for &'a F where F: RecordFields {}
+impl<'a, F> RecordFields for &'a F
+where
+ F: RecordFields,
+{
+ fn record(&self, visitor: &mut dyn Visit) {
+ F::record(*self, visitor)
+ }
+}
+
+// === blanket impls ===
+
+impl<T, V, F> MakeVisitor<T> for F
+where
+ F: Fn(T) -> V,
+ V: Visit,
+{
+ type Visitor = V;
+ fn make_visitor(&self, target: T) -> Self::Visitor {
+ (self)(target)
+ }
+}
+
+impl<T, Out, M> crate::sealed::Sealed<(T, Out)> for M
+where
+ M: MakeVisitor<T>,
+ M::Visitor: VisitOutput<Out>,
+{
+}
+
+impl<T, Out, M> MakeOutput<T, Out> for M
+where
+ M: MakeVisitor<T>,
+ M::Visitor: VisitOutput<Out>,
+{
+}
+
+impl<T, M> crate::sealed::Sealed<MakeExtMarker<T>> for M where M: MakeVisitor<T> + Sized {}
+
+impl<T, M> MakeExt<T> for M
+where
+ M: MakeVisitor<T> + Sized,
+ M: crate::sealed::Sealed<MakeExtMarker<T>>,
+{
+}
+
+#[derive(Debug)]
+#[doc(hidden)]
+pub struct MakeExtMarker<T> {
+ _p: PhantomData<T>,
+}
+
+#[derive(Debug)]
+#[doc(hidden)]
+pub struct RecordFieldsMarker {
+ _p: (),
+}
+
+#[cfg(all(test, feature = "alloc"))]
+#[macro_use]
+pub(in crate::field) mod test_util {
+ use super::*;
+ pub(in crate::field) use alloc::string::String;
+ use tracing_core::{
+ callsite::Callsite,
+ field::{Field, Value},
+ metadata::{Kind, Level, Metadata},
+ };
+
+ pub(crate) struct TestAttrs1;
+ pub(crate) struct TestAttrs2;
+
+ impl TestAttrs1 {
+ pub(crate) fn with<T>(f: impl FnOnce(Attributes<'_>) -> T) -> T {
+ let fieldset = TEST_META_1.fields();
+ let values = &[
+ (
+ &fieldset.field("question").unwrap(),
+ Some(&"life, the universe, and everything" as &dyn Value),
+ ),
+ (&fieldset.field("question.answer").unwrap(), None),
+ (
+ &fieldset.field("tricky").unwrap(),
+ Some(&true as &dyn Value),
+ ),
+ (
+ &fieldset.field("can_you_do_it").unwrap(),
+ Some(&true as &dyn Value),
+ ),
+ ];
+ let valueset = fieldset.value_set(values);
+ let attrs = tracing_core::span::Attributes::new(&TEST_META_1, &valueset);
+ f(attrs)
+ }
+ }
+
+ impl TestAttrs2 {
+ pub(crate) fn with<T>(f: impl FnOnce(Attributes<'_>) -> T) -> T {
+ let fieldset = TEST_META_1.fields();
+ let none = tracing_core::field::debug(&Option::<&str>::None);
+ let values = &[
+ (
+ &fieldset.field("question").unwrap(),
+ Some(&none as &dyn Value),
+ ),
+ (
+ &fieldset.field("question.answer").unwrap(),
+ Some(&42 as &dyn Value),
+ ),
+ (
+ &fieldset.field("tricky").unwrap(),
+ Some(&true as &dyn Value),
+ ),
+ (
+ &fieldset.field("can_you_do_it").unwrap(),
+ Some(&false as &dyn Value),
+ ),
+ ];
+ let valueset = fieldset.value_set(values);
+ let attrs = tracing_core::span::Attributes::new(&TEST_META_1, &valueset);
+ f(attrs)
+ }
+ }
+
+ struct TestCallsite1;
+ static TEST_CALLSITE_1: &'static dyn Callsite = &TestCallsite1;
+ static TEST_META_1: Metadata<'static> = tracing_core::metadata! {
+ name: "field_test1",
+ target: module_path!(),
+ level: Level::INFO,
+ fields: &["question", "question.answer", "tricky", "can_you_do_it"],
+ callsite: TEST_CALLSITE_1,
+ kind: Kind::SPAN,
+ };
+
+ impl Callsite for TestCallsite1 {
+ fn set_interest(&self, _: tracing_core::subscriber::Interest) {
+ unimplemented!()
+ }
+
+ fn metadata(&self) -> &Metadata<'_> {
+ &TEST_META_1
+ }
+ }
+
+ pub(crate) struct MakeDebug;
+ pub(crate) struct DebugVisitor<'a> {
+ writer: &'a mut dyn fmt::Write,
+ err: fmt::Result,
+ }
+
+ impl<'a> DebugVisitor<'a> {
+ pub(crate) fn new(writer: &'a mut dyn fmt::Write) -> Self {
+ Self {
+ writer,
+ err: Ok(()),
+ }
+ }
+ }
+
+ impl<'a> Visit for DebugVisitor<'a> {
+ fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
+ write!(self.writer, "{}={:?}", field, value).unwrap();
+ }
+ }
+
+ impl<'a> VisitOutput<fmt::Result> for DebugVisitor<'a> {
+ fn finish(self) -> fmt::Result {
+ self.err
+ }
+ }
+
+ impl<'a> VisitFmt for DebugVisitor<'a> {
+ fn writer(&mut self) -> &mut dyn fmt::Write {
+ self.writer
+ }
+ }
+
+ impl<'a> MakeVisitor<&'a mut dyn fmt::Write> for MakeDebug {
+ type Visitor = DebugVisitor<'a>;
+ fn make_visitor(&self, w: &'a mut dyn fmt::Write) -> DebugVisitor<'a> {
+ DebugVisitor::new(w)
+ }
+ }
+}