continuwuity/src/core/log/capture/layer.rs
Jason Volk d9054f5364 add backreference to layer in capture data struct
Signed-off-by: Jason Volk <jason@zemos.net>
2024-06-30 18:02:16 +00:00

84 lines
1.8 KiB
Rust

use std::{fmt, sync::Arc};
use tracing::field::{Field, Visit};
use tracing_core::{Event, Subscriber};
use tracing_subscriber::{layer::Context, registry::LookupSpan};
use super::{Capture, Data, State};
pub type Value = (&'static str, String);
pub struct Layer {
state: Arc<State>,
}
struct Visitor {
values: Vec<Value>,
}
impl Layer {
pub fn new(state: &Arc<State>) -> Self {
Self {
state: state.clone(),
}
}
}
impl fmt::Debug for Layer {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.debug_struct("capture::Layer").finish()
}
}
impl<S> tracing_subscriber::Layer<S> for Layer
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
self.state
.active
.read()
.expect("shared lock")
.iter()
.filter(|capture| filter(self, capture, event, &ctx))
.for_each(|capture| handle(self, capture, event, &ctx));
}
}
fn handle<S>(layer: &Layer, capture: &Capture, event: &Event<'_>, ctx: &Context<'_, S>)
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
let mut visitor = Visitor {
values: Vec::new(),
};
event.record(&mut visitor);
let mut closure = capture.closure.lock().expect("exclusive lock");
closure(Data {
layer,
event,
current: &ctx.current_span(),
values: Some(&mut visitor.values),
});
}
fn filter<S>(layer: &Layer, capture: &Capture, event: &Event<'_>, ctx: &Context<'_, S>) -> bool
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
capture.filter.as_ref().map_or(true, |filter| {
filter(Data {
layer,
event,
current: &ctx.current_span(),
values: None,
})
})
}
impl Visit for Visitor {
fn record_debug(&mut self, f: &Field, v: &dyn fmt::Debug) { self.values.push((f.name(), format!("{v:?}"))); }
fn record_str(&mut self, f: &Field, v: &str) { self.values.push((f.name(), v.to_owned())); }
}