Files
continuwuity/src/core/log/reload.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

82 lines
2.2 KiB
Rust
Raw Normal View History

use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
2024-05-09 15:59:08 -07:00
use tracing_subscriber::{EnvFilter, reload};
2024-05-09 15:59:08 -07:00
use crate::{Result, error};
2024-05-09 15:59:08 -07:00
/// We need to store a reload::Handle value, but can't name it's type explicitly
/// because the S type parameter depends on the subscriber's previous layers. In
/// our case, this includes unnameable 'impl Trait' types.
///
/// This is fixed[1] in the unreleased tracing-subscriber from the master
/// branch, which removes the S parameter. Unfortunately can't use it without
/// pulling in a version of tracing that's incompatible with the rest of our
/// deps.
///
/// To work around this, we define an trait without the S paramter that forwards
/// to the reload::Handle::reload method, and then store the handle as a trait
/// object.
///
/// [1]: <https://github.com/tokio-rs/tracing/pull/1035/commits/8a87ea52425098d3ef8f56d92358c2f6c144a28f>
pub trait ReloadHandle<L> {
fn current(&self) -> Option<L>;
2024-05-09 15:59:08 -07:00
fn reload(&self, new_value: L) -> Result<(), reload::Error>;
}
impl<L: Clone, S> ReloadHandle<L> for reload::Handle<L, S> {
fn current(&self) -> Option<L> { Self::clone_current(self) }
2024-06-09 10:23:06 +00:00
fn reload(&self, new_value: L) -> Result<(), reload::Error> { Self::reload(self, new_value) }
2024-05-09 15:59:08 -07:00
}
#[derive(Clone)]
pub struct LogLevelReloadHandles {
handles: Arc<Mutex<HandleMap>>,
2024-05-09 15:59:08 -07:00
}
type HandleMap = HashMap<String, Handle>;
type Handle = Box<dyn ReloadHandle<EnvFilter> + Send + Sync>;
2024-05-09 15:59:08 -07:00
impl LogLevelReloadHandles {
pub fn add(&self, name: &str, handle: Handle) {
self.handles
.lock()
.expect("locked")
.insert(name.into(), handle);
2024-05-09 15:59:08 -07:00
}
2024-07-11 00:42:49 +00:00
pub fn reload(&self, new_value: &EnvFilter, names: Option<&[&str]>) -> Result<()> {
self.handles
.lock()
.expect("locked")
2024-07-11 00:42:49 +00:00
.iter()
2024-11-28 23:33:33 +00:00
.filter(|(name, _)| names.is_some_and(|names| names.contains(&name.as_str())))
2024-07-11 00:42:49 +00:00
.for_each(|(_, handle)| {
_ = handle.reload(new_value.clone()).or_else(error::else_log);
});
2024-06-08 01:13:20 +00:00
2024-05-09 15:59:08 -07:00
Ok(())
}
#[must_use]
pub fn current(&self, name: &str) -> Option<EnvFilter> {
self.handles
.lock()
.expect("locked")
.get(name)
.map(|handle| handle.current())?
}
2024-05-09 15:59:08 -07:00
}
impl Default for LogLevelReloadHandles {
fn default() -> Self {
Self {
handles: Arc::new(HandleMap::new().into()),
}
}
}