mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-28 00:00:11 +02:00
trace: add program-wide default dispatcher (#1152)
## Motivation I was just trying to use tokio-trace for a greenfield project, but I was frustrated to discover that I couldn't really use it easily. I was using the [`runtime`](https://docs.rs/runtime/0.3.0-alpha.4/runtime/) crate, which transparently spawns a thread pool executor for futures. In that thread pool, there's no way to set a tokio-trace subscriber for the duration of each thread, since you don't control the thread initialization. You *might* be able to wrap every future you spawn with a subscriber call, but that's a lot of work. I was also confused because the documentation said that setting a subscriber in the main thread would use that subscriber for the rest of the program. That isn't the case, though -- the subscriber will be used only on the main thread, and not on worker threads, etc. ## Solution I added a function `set_global_default`, which works similarly to the `log` crate: ```rust tokio_trace::subscriber::set_global_default(FooSubscriber::new()); ``` The global subscriber (actually a global `Dispatch`) is a `static mut` protected by an atomic; implementation is copied from the `log` crate. It is used as a fallback if a thread has no `Dispatch` currently set. This is extremely simple to use, and doesn't break any existing functionality. Performance-wise, thread-local `Dispatch` lookup goes from ~4.5ns to ~5ns, according to the benchmarks. So, barely any runtime overhead. (Presumably there's a little compile-time overhead but idk how to measure that.) Since the atomic guard is only ever written once, it will be shared among a CPU's cores and read very cheaply. I added some docs to partially address #1151. I also switched the tokio-trace benchmarks to criterion because the nightly benchmarks weren't compiling (missing `dyn` flags?)
This commit is contained in:
committed by
Eliza Weisman
parent
5925ca7720
commit
36ed35c52c
+25
-3
@@ -366,6 +366,26 @@
|
||||
//! implementation compatible with `tokio-trace`. A `Subscriber` implements a
|
||||
//! way of collecting trace data, such as by logging it to standard output.
|
||||
//!
|
||||
//! There currently aren't too many subscribers to choose from. The best one to use right now
|
||||
//! is probably [`tokio-trace-fmt`], which logs to the terminal.
|
||||
//! The simplest way to use a subscriber is to call the `set_global_default` function:
|
||||
//!
|
||||
//! ```no_build
|
||||
//! #[macro_use]
|
||||
//! extern crate tokio_trace;
|
||||
//! let my_subscriber = FooSubscriber::new();
|
||||
//! tokio_trace::subscriber::set_global_default(my_subscriber).expect("setting tokio_trace default failed");
|
||||
//! ```
|
||||
//!
|
||||
//! Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when
|
||||
//! executables try to set the default later.
|
||||
//!
|
||||
//! This subscriber will be used as the default in all threads for the remainder of the duration
|
||||
//! of the program, similar to how loggers work in the `log` crate.
|
||||
//!
|
||||
//! In addition, you can locally override the default subscriber, using the `tokio` pattern
|
||||
//! of executing code in a context. For example:
|
||||
//!
|
||||
//! Unlike the `log` crate, `tokio-trace` does *not* use a global `Subscriber`
|
||||
//! which is initialized once. Instead, it follows the `tokio` pattern of
|
||||
//! executing code in a context. For example:
|
||||
@@ -399,9 +419,11 @@
|
||||
//! ```
|
||||
//!
|
||||
//! This approach allows trace data to be collected by multiple subscribers
|
||||
//! within different contexts in the program. Alternatively, a single subscriber
|
||||
//! may be constructed by the `main` function and all subsequent code executed
|
||||
//! with that subscriber as the default. Any trace events generated outside the
|
||||
//! within different contexts in the program. Note that the override only applies to the
|
||||
//! currently executing thread; other threads will not see the change from with_default.
|
||||
//! with that subscriber as the default.
|
||||
//!
|
||||
//! Any trace events generated outside the
|
||||
//! context of a subscriber will not be collected.
|
||||
//!
|
||||
//! The executable itself may use the `tokio-trace` crate to instrument itself
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//! Collects and records trace data.
|
||||
pub use tokio_trace_core::subscriber::*;
|
||||
|
||||
/// Sets this dispatch as the default for the duration of a closure.
|
||||
/// Sets this subscriber as the default for the duration of a closure.
|
||||
///
|
||||
/// The default dispatcher is used when creating a new [`Span`] or
|
||||
/// The default subscriber is used when creating a new [`Span`] or
|
||||
/// [`Event`], _if no span is currently executing_. If a span is currently
|
||||
/// executing, new spans or events are dispatched to the subscriber that
|
||||
/// tagged that span, instead.
|
||||
@@ -17,3 +17,24 @@ where
|
||||
{
|
||||
::dispatcher::with_default(&::Dispatch::new(subscriber), f)
|
||||
}
|
||||
|
||||
/// Sets this subscriber as the global default for the duration of the entire program.
|
||||
/// Will be used as a fallback if no thread-local subscriber has been set in a thread (using `with_default`.)
|
||||
///
|
||||
/// Can only be set once; subsequent attempts to set the global default will fail.
|
||||
/// Returns whether the initialization was successful.
|
||||
///
|
||||
/// Note: Libraries should *NOT* call `set_global_default()`! That will cause conflicts when
|
||||
/// executables try to set them later.
|
||||
///
|
||||
/// [span]: ../span/index.html
|
||||
/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
|
||||
/// [`Event`]: ../event/struct.Event.html
|
||||
pub fn set_global_default<S>(subscriber: S) -> Result<(), SetGlobalDefaultError>
|
||||
where
|
||||
S: Subscriber + Send + Sync + 'static,
|
||||
{
|
||||
::dispatcher::set_global_default(::Dispatch::new(subscriber))
|
||||
}
|
||||
|
||||
pub use tokio_trace_core::dispatcher::SetGlobalDefaultError;
|
||||
|
||||
Reference in New Issue
Block a user