diff --git a/examples/README.md b/examples/README.md index 3c9cd88e91..61a4383ae9 100644 --- a/examples/README.md +++ b/examples/README.md @@ -31,6 +31,8 @@ This directory contains a collection of examples that demonstrate the use of the debug a server under load in production. + `journald`: Demonstrates how to use `fmt` and `journald` layers to output to both the terminal and the system journal. + + `toggle-layers` : Demonstrates how Layers can be wrapped with an `Option` allowing + them to be dynamically toggled. - **tracing-futures**: + `spawny-thing`: Demonstrates the use of the `#[instrument]` attribute macro asynchronous functions. diff --git a/examples/examples/toggle-layers.rs b/examples/examples/toggle-layers.rs new file mode 100644 index 0000000000..f4cbe4b222 --- /dev/null +++ b/examples/examples/toggle-layers.rs @@ -0,0 +1,47 @@ +#![deny(rust_2018_idioms)] +/// This is a example showing how `Layer` can be enabled or disabled by +/// by wrapping them with an `Option`. This example shows `fmt` and `json` +/// being toggled based on the `json` command line flag. +/// +/// You can run this example by running the following command in a terminal +/// +/// ``` +/// cargo run --example toggle-layers -- json +/// ``` +/// +use clap::{App, Arg}; +use tracing::info; +use tracing_subscriber::{prelude::__tracing_subscriber_SubscriberExt, util::SubscriberInitExt}; + +#[path = "fmt/yak_shave.rs"] +mod yak_shave; + +fn main() { + let matches = App::new("fmt optional Example") + .version("1.0") + .arg( + Arg::with_name("json") + .help("Enabling json formatting of logs") + .required(false) + .takes_value(false), + ) + .get_matches(); + + let (json, plain) = if matches.is_present("json") { + (Some(tracing_subscriber::fmt::layer().json()), None) + } else { + (None, Some(tracing_subscriber::fmt::layer())) + }; + + tracing_subscriber::registry().with(json).with(plain).init(); + + let number_of_yaks = 3; + // this creates a new event, outside of any spans. + info!(number_of_yaks, "preparing to shave yaks"); + + let number_shaved = yak_shave::shave_all(number_of_yaks); + info!( + all_yaks_shaved = number_shaved == number_of_yaks, + "yak shaving completed." + ); +} diff --git a/tracing-subscriber/src/layer.rs b/tracing-subscriber/src/layer.rs index 01b111aad3..e3609c9b18 100644 --- a/tracing-subscriber/src/layer.rs +++ b/tracing-subscriber/src/layer.rs @@ -808,6 +808,102 @@ where } } +impl Layer for Option +where + L: Layer, + S: Subscriber, +{ + #[inline] + fn new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.new_span(attrs, id, ctx) + } + } + + #[inline] + fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { + match self { + Some(ref inner) => inner.register_callsite(metadata), + None => Interest::always(), + } + } + + #[inline] + fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool { + match self { + Some(ref inner) => inner.enabled(metadata, ctx), + None => true, + } + } + + #[inline] + fn max_level_hint(&self) -> Option { + match self { + Some(ref inner) => inner.max_level_hint(), + None => None, + } + } + + #[inline] + fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.on_record(span, values, ctx); + } + } + + #[inline] + fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.on_follows_from(span, follows, ctx); + } + } + + #[inline] + fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.on_event(event, ctx); + } + } + + #[inline] + fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.on_enter(id, ctx); + } + } + + #[inline] + fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.on_exit(id, ctx); + } + } + + #[inline] + fn on_close(&self, id: span::Id, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.on_close(id, ctx); + } + } + + #[inline] + fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<'_, S>) { + if let Some(ref inner) = self { + inner.on_id_change(old, new, ctx) + } + } + + #[doc(hidden)] + #[inline] + unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> { + if id == TypeId::of::() { + Some(self as *const _ as *const ()) + } else { + self.as_ref().and_then(|inner| inner.downcast_raw(id)) + } + } +} + #[cfg(feature = "registry")] #[cfg_attr(docsrs, doc(cfg(feature = "registry")))] impl<'a, L, S> LookupSpan<'a> for Layered