make tracing reload handles into a named map

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-10 22:28:56 +00:00
parent db3c718ddc
commit 0023b09f5b
3 changed files with 40 additions and 25 deletions

View file

@ -47,6 +47,8 @@ pub enum Error {
Regex(#[from] regex::Error),
#[error("Tracing filter error: {0}")]
TracingFilter(#[from] tracing_subscriber::filter::ParseError),
#[error("Tracing reload error: {0}")]
TracingReload(#[from] tracing_subscriber::reload::Error),
#[error("Image error: {0}")]
Image(#[from] image::error::ImageError),
#[error("Request error: {0}")]

View file

@ -1,7 +1,12 @@
use std::sync::Arc;
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use tracing_subscriber::{reload, EnvFilter};
use crate::{error, Result};
/// 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.
@ -24,32 +29,39 @@ impl<L, S> ReloadHandle<L> for reload::Handle<L, S> {
fn reload(&self, new_value: L) -> Result<(), reload::Error> { Self::reload(self, new_value) }
}
struct LogLevelReloadHandlesInner {
handles: Vec<Box<dyn ReloadHandle<EnvFilter> + Send + Sync>>,
}
/// Wrapper to allow reloading the filter on several several
/// [`tracing_subscriber::reload::Handle`]s at once, with the same value.
#[derive(Clone)]
pub struct LogLevelReloadHandles {
inner: Arc<LogLevelReloadHandlesInner>,
handles: Arc<Mutex<HandleMap>>,
}
type HandleMap = HashMap<String, Handle>;
type Handle = Box<dyn ReloadHandle<EnvFilter> + Send + Sync>;
impl LogLevelReloadHandles {
#[must_use]
pub fn new(handles: Vec<Box<dyn ReloadHandle<EnvFilter> + Send + Sync>>) -> Self {
Self {
inner: Arc::new(LogLevelReloadHandlesInner {
handles,
}),
}
pub fn add(&self, name: &str, handle: Handle) {
self.handles
.lock()
.expect("locked")
.insert(name.into(), handle);
}
pub fn reload(&self, new_value: &EnvFilter) -> Result<(), reload::Error> {
for handle in &self.inner.handles {
handle.reload(new_value.clone())?;
}
pub fn reload(&self, new_value: &EnvFilter) -> Result<()> {
self.handles
.lock()
.expect("locked")
.values()
.for_each(|handle| {
_ = handle.reload(new_value.clone()).or_else(error::else_log);
});
Ok(())
}
}
impl Default for LogLevelReloadHandles {
fn default() -> Self {
Self {
handles: Arc::new(HandleMap::new().into()),
}
}
}