Skip to main content

Crate tracing_reload

Crate tracing_reload 

Source
Expand description

Wrapper for a Layer to allow it to be dynamically modified at runtime. This is based on tracing_subscriber::reload.

This crate provides a Layer type implementing the Layer trait which wraps another type implementing the same trait. The inner value is pinned on construction so its memory address is stable. Reloads publish a new value and retire the old one instead of mutating in place, which together with pinning keeps pointers returned from downcast_raw valid. The one-time on_layer setup hook is forwarded through a transient mutable reference during construction, before any such pointer is handed out.

The inner value is reloaded by replacing it through Handle::reload_with (or Handle::reload); it is never mutated in place. Each reload publishes a new value and retires the previous one, which is kept alive so that pointers previously handed out by downcast_raw stay valid and all events in a given span can be routed to the same layer. Retired versions are reclaimed when the subscriber is dropped.

§Why to use this instead of tracing_subscriber::reload::Layer

This layer is built so that downcast_raw is possible through this layer. The price is leaked memory (and possibly other resources) on every reload.

That happens because downcast_raw returns a raw pointer and if we return a pointer to the inner layer, we need to guarantee that the pointer is valid for as long as someone has a reference to the layer. The method has no safety doc comment in tracing-subscriber and from other usage it is only clear that it should be valid for as long as the &self argument. But we can never know when that reference goes out of scope, we can only be sure it is safe to clean up once this Layer is dropped. Until then we have to keep around all layers we have downcasted to.

Furthermore, this layer tracks which version of the inner layer created a given span and routes on_event, on_enter, on_exit, and on_close to that layer even if a newer one is available. This is because some layers depend on information stored in span extensions which is added on span creation and may panic when reload happens at a wrong time.

§Examples

use tracing_reload::{Layer, Handle};
use tracing_subscriber::{filter, fmt, prelude::*};
let filter = filter::LevelFilter::WARN;
let (filter, reload_handle) = Layer::new(filter);
tracing_subscriber::registry()
  .with(filter)
  .with(fmt::Layer::default())
  .init();
info!("This will be ignored");
reload_handle.reload(filter::LevelFilter::INFO);
info!("This will be logged");

Reloading a Filtered layer:

use tracing_subscriber::{filter, fmt, reload, prelude::*};
let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
tracing_subscriber::registry()
  .with(filtered_layer)
  .init();
info!("This will be ignored");
reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO);
info!("This will be logged");

Structs§

Error
Indicates that an error occurred when accessing a reloadable layer.
Handle
Allows modifying the state of an associated reloadable layer.
Layer
Wraps another type implementing tracing_subscriber::layer::Layer or tracing_subscriber::layer::Filter, allowing it to be modified dynamically at runtime.
ReloadSubscriber
This is a fake subscriber that should not be constructed by user-code.

Enums§

ReloadRouting
Determines how new spans are routed when layers are reloaded.