Krolyxon
Commit 4e844bb

ferreniumsrclogging.rs

56 lines · 1.7 KB · Rust

1//! stderr logging. Under systemd (`JOURNAL_STREAM` set) timestamps and colors
2//! are dropped because journald adds its own. `RUST_LOG` overrides
3//! `log.level`; otherwise the level follows the config across reloads.
4
5use std::io::IsTerminal;
6use std::sync::OnceLock;
7
8use tracing_subscriber::prelude::*;
9use tracing_subscriber::{EnvFilter, Registry, reload};
10
11use crate::config::Config;
12
13static HANDLE: OnceLock<reload::Handle<EnvFilter, Registry>> = OnceLock::new();
14
15pub fn init(config: &Config) {
16 let (filter, handle) = reload::Layer::new(filter_for(config));
17 let fmt = tracing_subscriber::fmt::layer()
18 .with_writer(std::io::stderr)
19 .with_target(false);
20 let registry = tracing_subscriber::registry().with(filter);
21 if std::env::var_os("JOURNAL_STREAM").is_some() {
22 registry.with(fmt.without_time().with_ansi(false)).init();
23 } else {
24 registry
25 .with(fmt.with_ansi(std::io::stderr().is_terminal()))
26 .init();
27 }
28 let _ = HANDLE.set(handle);
29}
30
31/// Apply `log.level` from a freshly loaded config.
32pub fn apply(config: &Config) {
33 if rust_log().is_some() {
34 return;
35 }
36 if let Some(handle) = HANDLE.get() {
37 let _ = handle.reload(filter_for(config));
38 }
39}
40
41fn rust_log() -> Option<String> {
42 std::env::var("RUST_LOG")
43 .ok()
44 .filter(|v| !v.trim().is_empty())
45}
46
47fn filter_for(config: &Config) -> EnvFilter {
48 if let Some(spec) = rust_log() {
49 match EnvFilter::try_new(&spec) {
50 Ok(filter) => return filter,
51 Err(e) => eprintln!("ignoring invalid RUST_LOG {spec:?}: {e}"),
52 }
53 }
54 // Validated at config load time.
55 EnvFilter::try_new(&config.log.level).unwrap_or_else(|_| EnvFilter::new("info"))
56}