reth_tracing/
log_handle.rs1use tracing::level_filters::LevelFilter;
8use tracing_subscriber::{reload, EnvFilter, Registry};
9
10pub type LogFilterReloadHandle = reload::Handle<EnvFilter, Registry>;
12
13#[derive(Debug)]
15pub struct LogFilterHandle {
16 handles: Vec<LogFilterReloadHandle>,
17}
18
19impl LogFilterHandle {
20 const fn new() -> Self {
22 Self { handles: Vec::new() }
23 }
24
25 fn push(&mut self, handle: LogFilterReloadHandle) {
27 self.handles.push(handle);
28 }
29
30 const fn is_available(&self) -> bool {
32 !self.handles.is_empty()
33 }
34
35 fn reload_all(
37 &self,
38 make_filter: impl Fn() -> Result<EnvFilter, String>,
39 ) -> Result<(), String> {
40 for handle in &self.handles {
41 let filter = make_filter()?;
42 handle.reload(filter).map_err(|e| e.to_string())?;
43 }
44 Ok(())
45 }
46}
47
48static LOG_HANDLE: std::sync::Mutex<LogFilterHandle> =
50 std::sync::Mutex::new(LogFilterHandle::new());
51
52pub fn install_log_handle(handle: LogFilterReloadHandle) {
56 LOG_HANDLE.lock().expect("log handle poisoned").push(handle);
57}
58
59pub fn log_handle_available() -> bool {
61 LOG_HANDLE.lock().expect("log handle poisoned").is_available()
62}
63
64pub fn set_log_verbosity(level: usize) -> Result<(), String> {
77 let guard = LOG_HANDLE.lock().expect("log handle poisoned");
78
79 if !guard.is_available() {
80 return Err("Log filter reload not available".to_string());
81 }
82
83 let level_filter = match level {
84 0 => LevelFilter::OFF,
85 1 => LevelFilter::ERROR,
86 2 => LevelFilter::WARN,
87 3 => LevelFilter::INFO,
88 4 => LevelFilter::DEBUG,
89 _ => LevelFilter::TRACE,
90 };
91
92 guard.reload_all(|| {
93 Ok(EnvFilter::builder().with_default_directive(level_filter.into()).parse_lossy(""))
94 })
95}
96
97pub fn set_log_vmodule(pattern: &str) -> Result<(), String> {
110 let guard = LOG_HANDLE.lock().expect("log handle poisoned");
111
112 if !guard.is_available() {
113 return Err("Log filter reload not available".to_string());
114 }
115
116 if pattern.trim().is_empty() {
117 guard.reload_all(|| {
118 Ok(EnvFilter::builder()
119 .with_default_directive(LevelFilter::INFO.into())
120 .parse_lossy(""))
121 })
122 } else {
123 EnvFilter::try_new(pattern).map_err(|e| format!("Invalid filter pattern: {e}"))?;
125 guard.reload_all(|| {
126 EnvFilter::try_new(pattern).map_err(|e| format!("Invalid filter pattern: {e}"))
127 })
128 }
129}