Skip to main content

rustbridge_logging/
reload.rs

1//! Dynamic log level reloading support
2
3use once_cell::sync::OnceCell;
4use parking_lot::Mutex;
5use rustbridge_core::LogLevel;
6use tracing_subscriber::filter::LevelFilter;
7use tracing_subscriber::reload;
8
9/// Handle for dynamically reloading the log level filter
10pub struct ReloadHandle {
11    handle: Mutex<Option<reload::Handle<LevelFilter, tracing_subscriber::Registry>>>,
12}
13
14impl ReloadHandle {
15    /// Create a new reload handle
16    pub fn new() -> Self {
17        Self {
18            handle: Mutex::new(None),
19        }
20    }
21
22    /// Get the global reload handle
23    pub fn global() -> &'static ReloadHandle {
24        static INSTANCE: OnceCell<ReloadHandle> = OnceCell::new();
25        INSTANCE.get_or_init(ReloadHandle::new)
26    }
27
28    /// Set the reload handle (called during initialization)
29    pub fn set_handle(&self, handle: reload::Handle<LevelFilter, tracing_subscriber::Registry>) {
30        *self.handle.lock() = Some(handle);
31    }
32
33    /// Reload the filter to use a new log level
34    pub fn reload_level(&self, level: LogLevel) -> Result<(), String> {
35        let guard = self.handle.lock();
36        if let Some(handle) = guard.as_ref() {
37            let filter = convert_level_to_filter(level);
38            handle
39                .reload(filter)
40                .map_err(|e| format!("Failed to reload filter: {}", e))?;
41            Ok(())
42        } else {
43            Err("Reload handle not initialized".to_string())
44        }
45    }
46
47    /// Clear the reload handle
48    ///
49    /// This should be called when the last plugin shuts down to ensure
50    /// the handle doesn't persist across plugin reload cycles.
51    pub fn clear(&self) {
52        *self.handle.lock() = None;
53    }
54}
55
56impl Default for ReloadHandle {
57    fn default() -> Self {
58        Self::new()
59    }
60}
61
62/// Convert LogLevel to tracing LevelFilter
63fn convert_level_to_filter(level: LogLevel) -> LevelFilter {
64    match level {
65        LogLevel::Trace => LevelFilter::TRACE,
66        LogLevel::Debug => LevelFilter::DEBUG,
67        LogLevel::Info => LevelFilter::INFO,
68        LogLevel::Warn => LevelFilter::WARN,
69        LogLevel::Error => LevelFilter::ERROR,
70        LogLevel::Off => LevelFilter::OFF,
71    }
72}