1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
//! Logging: a compact fmt logger whose filter can be replaced while the node runs
//! (`/admin/log`), and, with the `tokio-console` feature, a tokio-console layer.
//!
//! The filter starts from `RUST_LOG`, or `info` without it. It applies to the fmt
//! logger only, so the console layer keeps getting the runtime events it needs.
use std::sync::OnceLock;
use anyhow::{anyhow, Result};
use tracing_subscriber::{prelude::*, reload, EnvFilter, Registry};
type FilterHandle = reload::Handle<EnvFilter, Registry>;
static FILTER: OnceLock<FilterHandle> = OnceLock::new();
/// Installs the global subscriber. Call once, first thing in main.
pub(crate) fn init() {
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let (filter, handle) = reload::Layer::new(filter);
let registry = tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer().compact().with_filter(filter));
#[cfg(feature = "tokio-console")]
let registry = registry.with(
console_subscriber::spawn()
.with_filter(EnvFilter::new("tokio=trace,runtime=trace")),
);
registry.init();
let _ = FILTER.set(handle);
}
/// The filter in effect, in `RUST_LOG` syntax.
pub(crate) fn filter() -> Result<String> {
handle()?
.with_current(|filter| filter.to_string())
.map_err(|error| anyhow!("Reading the log filter: {error}"))
}
/// Replaces the filter. `directives` uses `RUST_LOG` syntax, e.g.
/// `info,continuum::swarm::sync=trace`. An invalid one leaves the old filter in place.
pub(crate) fn set_filter(directives: &str) -> Result<String> {
let filter = EnvFilter::try_new(directives)
.map_err(|error| anyhow!("Invalid log filter {directives:?}: {error}"))?;
let applied = filter.to_string();
handle()?
.reload(filter)
.map_err(|error| anyhow!("Replacing the log filter: {error}"))?;
Ok(applied)
}
fn handle() -> Result<&'static FilterHandle> {
FILTER
.get()
.ok_or_else(|| anyhow!("Logging is not initialised"))
}
|