use std::fmt::{self, Debug};
use std::marker::PhantomData;
use uninode::UniNode;
use tracing::subscriber::{Interest, Subscriber};
use tracing::{span, Event, Metadata};
use tracing_subscriber::filter::targets::Targets;
use tracing_subscriber::filter::LevelFilter;
use tracing_subscriber::layer::{Context, Filter, Layer};
use tracing_subscriber::registry::LookupSpan;
pub fn create_level_filter(level: &str) -> LevelFilter {
match level {
"trace" => LevelFilter::TRACE,
"debug" => LevelFilter::DEBUG,
"info" => LevelFilter::INFO,
"warn" => LevelFilter::WARN,
"error" => LevelFilter::ERROR,
_ => LevelFilter::OFF,
}
}
pub fn create_target_filter(cfg: &UniNode) -> Targets {
let mut retval = Targets::new();
for target in cfg.clone().to_array().unwrap() {
let target = target.as_str().ok().and_then(|v| v.split_once('='));
if let Some((target, level)) = target {
let level = create_level_filter(level);
retval = retval.with_target(target, level);
}
}
retval
}
#[derive(Clone)]
pub struct Filtered<L, F, S> {
filter: F,
layer: L,
_s: PhantomData<fn(S)>,
}
impl<L, F, S> Filtered<L, F, S>
where
F: Filter<S> + 'static,
{
pub fn new(layer: L, filter: F) -> Self {
Self {
layer,
filter,
_s: PhantomData,
}
}
fn enabled(&self, meta: &Metadata<'_>, ctx: &Context<S>) -> bool {
Filter::enabled(&self.filter, meta, ctx)
}
}
impl<F, L, S> Debug for Filtered<F, L, S>
where
F: Debug,
L: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CombFiltered")
.field("filter", &self.filter)
.field("layer", &self.layer)
.finish()
}
}
impl<S, L, F> Layer<S> for Filtered<L, F, S>
where
S: Subscriber + for<'span> LookupSpan<'span> + 'static + Debug,
for<'a> <S as LookupSpan<'a>>::Data: Debug,
F: Filter<S> + Layer<S> + 'static,
L: Layer<S>,
{
fn on_layer(&mut self, subscriber: &mut S) {
self.filter.on_layer(subscriber);
self.layer.on_layer(subscriber);
}
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
let interest = self.filter.callsite_enabled(metadata);
if !interest.is_never() {
self.layer.register_callsite(metadata);
}
Interest::always()
}
fn enabled(&self, meta: &Metadata, ctx: Context<S>) -> bool {
let enabled = self.enabled(meta, &ctx);
if enabled {
self.layer.enabled(meta, ctx)
} else {
true
}
}
fn on_new_span(&self, attrs: &span::Attributes, id: &span::Id, ctx: Context<S>) {
self.layer.on_new_span(attrs, id, ctx.clone())
}
fn max_level_hint(&self) -> Option<LevelFilter> {
Filter::max_level_hint(&self.filter)
}
fn on_record(&self, id: &span::Id, values: &span::Record, ctx: Context<S>) {
if let Some(meta) = ctx.metadata(id) {
if self.enabled(meta, &ctx) {
self.layer.on_record(id, values, ctx)
}
}
}
fn on_follows_from(&self, id: &span::Id, follows: &span::Id, ctx: Context<'_, S>) {
if let (Some(id_meta), Some(f_meta)) = (ctx.metadata(id), ctx.metadata(follows)) {
if self.enabled(id_meta, &ctx) && self.enabled(f_meta, &ctx) {
self.layer.on_follows_from(id, follows, ctx)
}
}
}
fn on_event(&self, event: &Event, ctx: Context<S>) {
if self.enabled(event.metadata(), &ctx) {
self.layer.on_event(event, ctx);
}
}
fn on_enter(&self, id: &span::Id, ctx: Context<S>) {
if let Some(meta) = ctx.metadata(id) {
if self.enabled(meta, &ctx) {
self.layer.on_enter(id, ctx)
}
}
}
fn on_exit(&self, id: &span::Id, ctx: Context<S>) {
if let Some(meta) = ctx.metadata(id) {
if self.enabled(meta, &ctx) {
self.layer.on_exit(id, ctx)
}
}
}
fn on_close(&self, id: span::Id, ctx: Context<S>) {
if let Some(meta) = ctx.metadata(&id) {
if self.enabled(meta, &ctx) {
self.layer.on_close(id, ctx)
}
}
}
fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: Context<S>) {
if let Some(meta) = ctx.metadata(old) {
if self.enabled(meta, &ctx) {
self.layer.on_id_change(old, new, ctx)
}
}
}
}