(Jin Qing's Column, Dec., 2021)
https://github.com/tokio-rs/tracing
Switch to tag tracing-0.1.29 first. The master's examples can not build. Subscriber is renaming to collector on master.
tracingsubscriber in 0.1.29 has been renamed to tracingcollect on master.
The example is using tracing_subscriber::fmt, which can be configured by RUST_LOG env val.
By default, no log is output. Set RUST_LOG=info before running, and the log is:
Dec 25 10:23:11.200 INFO tracing_test: preparing to shave yaks number_of_yaks=3
Dec 25 10:23:11.203 INFO tracing_test: yak shaving completed. all_yaks_shaved=true
RUST_LOG is defined in env_logger
It is slightly different from the github.
Span filter? [my_span]=info
https://docs.rs/tracing/0.1.29/tracing/
The document is much more detailed than github and crates.io.
Run example:
cargo run --example counters
fmt-multiple-writers:
tracing_appender::rolling::hourly(".", ...
.with(fmt::Layer::new().with_writer(non_blocking).with_ansi(false));
tower-load
https://github.com/tokio-rs/tracing/issues/1629 tracing_subscriber::reload
They use the same tracing_subscriber::reload::Handle::reload()
https://docs.rs/tracing-subscriber/0.3.4/tracing_subscriber/layer/index.html#filtering-with-layers
It is desired to reconfigure the log filter in the runtime by SIGHUP, or watch configure file change. It can use notify crate to watch file.
use anyhow::{anyhow, Context as _, Result};
use hotwatch::{Event, Hotwatch};
use std::{fs, thread, time::Duration};
use tracing::{debug, info, warn, Subscriber};
use tracing_subscriber::{reload::Handle, EnvFilter};
const CFG: &str = "cfg.txt";
fn main() -> Result<()> {
let builder = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_filter_reloading();
let handle = builder.reload_handle();
builder
.try_init()
.map_err(|e| anyhow!(e))
.context("failed to init subscriber builder")?;
tracing::info!("Before reload");
reload_cfg(handle.clone());
let mut hotwatch = Hotwatch::new().context("hotwatch failed to initialize!")?;
hotwatch
.watch(CFG, move |event: Event| {
if let Event::Write(_) = event {
reload_cfg(handle.clone());
}
})
.context("failed to watch file")?;
for i in 0..999 {
info!(i);
thread::sleep(Duration::from_secs(1));
}
Ok(())
}
fn reload_cfg<S: Subscriber + 'static>(handle: Handle<EnvFilter, S>) {
let res = try_reload_cfg(handle);
match res {
Ok(_) => debug!("reload cfg OK"),
Err(e) => warn!("reload cfg error: {:?}", e),
}
}
fn try_reload_cfg<S: Subscriber + 'static>(handle: Handle<EnvFilter, S>) -> Result<()> {
let contents = fs::read_to_string(CFG).context("something went wrong reading the file")?;
let contents = contents.trim();
debug!("reload cfg: {:?}", contents);
let new_filter = contents
.parse::<EnvFilter>()
.map_err(|e| anyhow!(e))
.context("failed to parse env filter")?;
handle.reload(new_filter).context("handle reload error")
}
Registry
] type provided by this crate is the only [Subscriber
] implementation capable of participating in per-layer filtering.