-
Notifications
You must be signed in to change notification settings - Fork 825
Description
Feature Request
Crates
tracing-subscriber
Motivation
There are many places I want to pipe my log events:
stderr
- a log file
- The GUI
- the network
- …
These can all be implemented as Layer
s.
The first thing I want to add is the stderr
and file layers. The GUI and the network layers I want to add later once the GUI and network connections are up and running. That way any problems with the GUI/network setup is properly logged to stdout and to file.
In other words: I want to dynamically add layers as the program runs.
Proposal
I propose some sort of simple API along the lines of tracing_subscriber::registry().add(layer);
Prior art
My own C++ logging Loguru has a simple method for adding new log sinks (https://emilk.github.io/loguru/index.html#callbacks):
loguru::add_callback("network_logger", user_data, logging_function, loguru::Verbosity_INFO);
This lets different sub-modules of an application can easily add new log sinks at will.
Alternatives
As I was trying to get this work, several helpful people on Discord pointed me towards tracing_subscriber::reload
.
I've tried to get it to work, but so far I've failed. My code thus far:
use tracing_subscriber::prelude::*;
let stdout_layer = tracing_subscriber::fmt::layer().with_filter(tracing_subscriber::EnvFilter::from_default_env());
let tracing_layers: Vec<Box<dyn tracing_subscriber::layer::Layer<_> + 'static> = vec![Box::new(stdout_layer)];
let (tracing_layers, reload_handle) = tracing_subscriber::reload::Layer::new(tracing_layers);
tracing_subscriber::registry().with(tracing_layers).init();
// set up GUI or network connect or similar, then:
reload_handle.modify(|layers| {
let gui_layer = GuiLayer::new(gui_handle);
layers.push(Box::new(gui_layer));
});
There are several issues with this approach:
- It is using a lot of different features that are hard to find ("Vec implements Layer!")
- It is too difficult to use (I can't get it to compile)
- It requires one to keep track of the
reload_handle
- It is VERY verbose
Perhaps all the above issues could be solved by an tracing_subscriber
expert plus a little bit of documentation. I don't know - I'm not an expert :)
The error message for the above code:
1 error[E0277]: the size for values of type `dyn tracing_subscriber::Layer<tracing_subscriber::Registry>` cannot be known at compilation time ▐
--> examples/rust/api_demo/src/main.rs:652:41 ▐
| ▐
652 | tracing_subscriber::registry().with(tracing_layers).init();
| ---- ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `std::marker::Sized` is not implemented for `dyn tracing_subscriber::Layer<tracing_subscriber::Registry>`
= help: the trait `tracing_subscriber::Layer<S>` is implemented for `tracing_subscriber::reload::Layer<L, S>`
= note: required for `std::boxed::Box<dyn tracing_subscriber::Layer<tracing_subscriber::Registry>>` to implement `tracing_subscriber::Layer<tracing_subscriber::Registry>`
= note: 2 redundant requirements hidden
= note: required for `tracing_subscriber::reload::Layer<std::vec::Vec<std::boxed::Box<dyn tracing_subscriber::Layer<...>>>, ...>` to implement `tracing_subscriber::Layer<tracing_subscriber::Registry>`
= note: the full type name has been written to '/Users/emilk/code/rerun/rerun/target/debug/deps/api_demo-118a8d78b3eddbda.long-type-14231036155949571826.txt'
note: required by a bound in `tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt::with`
--> /Users/emilk/.cargo/registry/src/github.com-1ecc6299db9ec823/tracing-subscriber-0.3.16/src/layer/mod.rs:1485:12
|
1485 | L: Layer<Self>,
| ^^^^^^^^^^^ required by this bound in `tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt::with`