Skip to content
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
2 changes: 2 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
47 changes: 47 additions & 0 deletions examples/examples/toggle-layers.rs
Original file line number Diff line number Diff line change
@@ -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();
Comment on lines +30 to +36
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice to have an abbreviated version of this example in the docs for the Layer trait. Maybe also a version showing runtime reloading in the layer::reload docs.


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."
);
}
96 changes: 96 additions & 0 deletions tracing-subscriber/src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,102 @@ where
}
}

impl<L, S> Layer<S> for Option<L>
where
L: Layer<S>,
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<LevelFilter> {
match self {
Some(ref inner) => inner.max_level_hint(),
None => None,
}
Comment on lines +841 to +844
Copy link
Member

Choose a reason for hiding this comment

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

Nit, take it or leave it: this could also be expressed using Option::and_then, like this:

Suggested change
match self {
Some(ref inner) => inner.max_level_hint(),
None => None,
}
self.and_then(Layer::max_level_hint)

}

#[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::<Self>() {
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<L, S>
Expand Down