Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subscriber: "implementing FormatEvent" docs #1727

Merged
merged 5 commits into from
Nov 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 68 additions & 18 deletions tracing-subscriber/src/fmt/format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,55 @@ use fmt::{Debug, Display};

/// A type that can format a tracing [`Event`] to a [`Writer`].
///
/// `FormatEvent` is primarily used in the context of [`fmt::Collector`] or [`fmt::Subscriber`].
/// Each time an event is dispatched to [`fmt::Collector`] or [`fmt::Subscriber`],
/// the collector or subscriber forwards it to its associated `FormatEvent` to emit a log message.
/// `FormatEvent` is primarily used in the context of [`fmt::Collector`] or
/// [`fmt::Subscriber`]. Each time an event is dispatched to [`fmt::Collector`]
/// or [`fmt::Subscriber`], the collector or subscriber forwards it to its
/// associated `FormatEvent` to emit a log message.
///
/// This trait is already implemented for function pointers with the same
/// signature as `format_event`.
///
/// # Arguments
///
/// The following arguments are passed to `FormatEvent::format_event`:
///
/// * A [`FmtContext`]. This is an extension of the [`subscribe::Context`] type,
/// which can be used for accessing stored information such as the current
/// span context an event occurred in.
///
/// In addition, [`FmtContext`] exposes access to the [`FormatFields`]
/// implementation that the subscriber was configured to use via the
/// [`FmtContext::field_format`] method. This can be used when the
/// [`FormatEvent`] implementation needs to format the event's fields.
///
/// For convenience, [`FmtContext`] also [implements `FormatFields`],
/// forwarding to the configured [`FormatFields`] type.
///
/// * A [`Writer`] to which the formatted representation of the event is
/// written. This type implements the [`std::fmt::Write`] trait, and therefore
/// can be used with the [`std::write!`] and [`std::writeln!`] macros, as well
/// as calling [`std::fmt::Write`] methods directly.
///
/// The [`Writer`] type also implements additional methods that provide
/// information about how the event should be formatted. The
/// [`Writer::has_ansi_escapes`] method indicates whether [ANSI terminal
/// escape codes] are supported by the underlying I/O writer that the event
/// will be written to. If this returns `true`, the formatter is permitted to
/// use ANSI escape codes to add colors and other text formatting to its
/// output. If it returns `false`, the event will be written to an output that
/// does not support ANSI escape codes (such as a log file), and they should
/// not be emitted.
///
/// Crates like [`ansi_term`] and [`owo-colors`] can be used to add ANSI
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol, that's a good name

/// escape codes to formatted output.
///
/// * The actual [`Event`] to be formatted.
///
/// # Examples
///
/// This example re-implements a simiplified version of this crate's [default
/// formatter]:
///
/// ```rust
/// use std::fmt;
/// use tracing_core::{Collect, Event};
Expand All @@ -67,31 +107,25 @@ use fmt::{Debug, Display};
/// mut writer: format::Writer<'_>,
/// event: &Event<'_>,
/// ) -> fmt::Result {
/// // Write level and target
/// let level = *event.metadata().level();
/// let target = event.metadata().target();
/// write!(
/// writer,
/// "{} {}: ",
/// level,
/// target,
/// )?;
/// // Format values from the event's's metadata:
/// let metadata = event.metadata();
/// write!(&mut writer, "{} {}: ", metadata.level(), metadata.target())?;
///
/// // Write spans and fields of each span
/// // Format all the spans in the event's span context.
/// ctx.visit_spans(|span| {
/// write!(writer, "{}", span.name())?;
///
/// let ext = span.extensions();
///
/// // `FormattedFields` is a a formatted representation of the span's
/// // `FormattedFields` is a formatted representation of the span's
/// // fields, which is stored in its extensions by the `fmt` layer's
/// // `new_span` method. The fields will have been formatted
/// // by the same field formatter that's provided to the event
/// // formatter in the `FmtContext`.
/// let ext = span.extensions();
/// let fields = &ext
/// .get::<FormattedFields<N>>()
/// .expect("will never be `None`");
///
/// // Skip formatting the fields if the span had no fields.
/// if !fields.is_empty() {
/// write!(writer, "{{{}}}", fields)?;
/// }
Expand All @@ -106,6 +140,13 @@ use fmt::{Debug, Display};
/// writeln!(writer)
/// }
/// }
///
/// let _subscriber = tracing_subscriber::fmt()
/// .event_format(MyFormatter)
/// .init();
///
/// let _span = tracing::info_span!("my_span", answer = 42).entered();
/// tracing::info!(question = "life, the universe, and everything", "hello world");
/// ```
///
/// This formatter will print events like this:
Expand All @@ -116,7 +157,14 @@ use fmt::{Debug, Display};
///
/// [`fmt::Collector`]: super::Collector
/// [`fmt::Subscriber`]: super::Subscriber
/// [`subscribe::Context`]: crate::subscribe::Context
/// [`Event`]: tracing::Event
/// [implements `FormatFields`]: super::FmtContext#impl-FormatFields<'writer>
/// [ANSI terminal escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code
/// [`Writer::has_ansi_escapes`]: Writer::has_ansi_escapes
/// [`ansi_term`]: https://crates.io/crates/ansi_term
/// [`owo-colors`]: https://crates.io/crates/owo-colors
/// [default formatter]: Full
pub trait FormatEvent<C, N>
where
C: Collect + for<'a> LookupSpan<'a>,
Expand Down Expand Up @@ -373,14 +421,16 @@ impl<'writer> Writer<'writer> {
self.writer.write_fmt(args)
}

/// Returns `true` if ANSI escape codes may be used to add colors
/// Returns `true` if [ANSI escape codes] may be used to add colors
/// and other formatting when writing to this `Writer`.
///
/// If this returns `false`, formatters should not emit ANSI escape codes.
///
/// [ANSI escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code
pub fn has_ansi_escapes(&self) -> bool {
self.is_ansi
}

pub(in crate::fmt::format) fn bold(&self) -> Style {
#[cfg(feature = "ansi")]
{
Expand Down
55 changes: 46 additions & 9 deletions tracing-subscriber/src/fmt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! A Collector for formatting and logging `tracing` data.
//!
//! ## Overview
//! # Overview
//!
//! [`tracing`] is a framework for instrumenting Rust programs with context-aware,
//! structured, event-based diagnostic information. This crate provides an
//! implementation of the [`Collect`] trait that records `tracing`'s `Event`s
//! and `Span`s by formatting them as text and logging them to stdout.
//!
//! ## Usage
//! # Usage
//!
//! First, add this to your `Cargo.toml` file:
//!
Expand Down Expand Up @@ -43,12 +43,12 @@
//! **Note**: This should **not** be called by libraries. Libraries should use
//! [`tracing`] to publish `tracing` `Event`s.
//!
//! ## Configuration
//! # Configuration
//!
//! You can configure a collector instead of using the defaults with
//! the following functions:
//!
//! ### Collector
//! ## Collector
//!
//! The [`FmtCollector`] formats and records `tracing` events as line-oriented logs.
//! You can create one by calling:
Expand All @@ -62,7 +62,7 @@
//! The configuration methods for [`FmtCollector`] can be found in
//! [`fmtBuilder`].
//!
//! ### Formatters
//! ## Formatters
//!
//! The output format used by the subscriber and collector in this module is
//! represented by implementing the [`FormatEvent`] trait, and can be
Expand Down Expand Up @@ -223,7 +223,44 @@
//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.875&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;yak shaving completed&quot;,&quot;all_yaks_shaved&quot;:false},&quot;target&quot;:&quot;fmt_json&quot;}
//! </pre>
//!
//! ### Filters
//! ### Customizing Formatters
//!
//! The formatting of log lines for spans and events is controlled by two
//! traits, [`FormatEvent`] and [`FormatFields`]. The [`FormatEvent`] trait
//! determines the overall formatting of the log line, such as what information
//! from the event's metadata and span context is included and in what order.
//! The [`FormatFields`] trait determines how fields &mdash; both the event's
//! fields and fields on spans &mdash; are formatted.
Comment on lines +232 to +233
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the use of &mdash; instead of intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can't remember the hotkey for typing a literal em dash on my keyboard...

//!
//! The [`fmt::format`] module provides several types which implement these traits,
//! many of which expose additional configuration options to customize their
//! output. The [`format::Format`] type implements common configuration used by
//! all the formatters provided in this crate, and can be used as a builder to
//! set specific formatting settings. For example:
//!
//! ```
//! use tracing_subscriber::fmt;
//!
//! // Configure a custom event formatter
//! let format = fmt::format()
//! .with_level(false) // don't include levels in formatted output
//! .with_target(false) // don't include targets
//! .with_thread_ids(true) // include the thread ID of the current thread
//! .with_thread_names(true) // include the name of the current thread
//! .compact(); // use the `Compact` formatting style.
//!
//! // Create a `fmt` collector that uses our custom event format, and set it
//! // as the default.
//! tracing_subscriber::fmt()
//! .event_format(format)
//! .init();
//! ```
//!
//! However, if a specific output format is needed, other crates can
//! also implement [`FormatEvent`] and [`FormatFields`]. See those traits'
//! documentation for details on how to implement them.
//!
//! ## Filters
//!
//! If you want to filter the `tracing` `Events` based on environment
//! variables, you can use the [`EnvFilter`] as follows:
Expand Down Expand Up @@ -257,7 +294,7 @@
//! // collector multiple times
//! ```
//!
//! ### Composing Subscribers
//! ## Composing Subscribers
//!
//! Composing an [`EnvFilter`] `Subscribe` and a [format `Subscribe`](super::fmt::Subscriber):
//!
Expand All @@ -283,9 +320,9 @@
//! [`filter`]: super::filter
//! [`fmtBuilder`]: CollectorBuilder
//! [`FmtCollector`]: Collector
//! [`Collect`]:
//! https://docs.rs/tracing/latest/tracing/trait.Collect.html
//! [`Collect`]: https://docs.rs/tracing/latest/tracing/trait.Collect.html
//! [`tracing`]: https://crates.io/crates/tracing
//! [`fmt::format`]: mod@crate::fmt::format
use std::{any::TypeId, error::Error, io, ptr::NonNull};
use tracing_core::{collect::Interest, span, Event, Metadata};

Expand Down
2 changes: 1 addition & 1 deletion tracing-subscriber/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
//!
//! - [`tracing-log`]: Enables better formatting for events emitted by `log`
//! macros in the `fmt` subscriber. Enabled by default.
//! - [`time`]: Enables support for using the [`time` crate] for timestamp
//! - [`time`][`time` crate]: Enables support for using the [`time` crate] for timestamp
//! formatting in the `fmt` subscriber.
//! - [`smallvec`]: Causes the `EnvFilter` type to use the `smallvec` crate (rather
//! than `Vec`) as a performance optimization. Enabled by default.
Expand Down