turbopack_trace_utils/
filter_layer.rs

1use std::str::FromStr;
2
3use anyhow::Result;
4use rustc_hash::FxHashMap;
5use tracing::{Subscriber, level_filters::LevelFilter};
6use tracing_subscriber::Layer;
7
8pub struct FilterLayer {
9    config: FxHashMap<String, LevelFilter>,
10    global_level: LevelFilter,
11}
12
13impl FilterLayer {
14    pub fn try_new(input: &str) -> Result<Self> {
15        let mut config = FxHashMap::default();
16        let mut global_level = LevelFilter::OFF;
17        for entry in input.split(',') {
18            if entry.is_empty() {
19                continue;
20            }
21            let mut parts = entry.splitn(2, '=');
22            let target = parts.next().unwrap();
23            let level = parts.next().unwrap_or("trace");
24            let level = LevelFilter::from_str(level).unwrap();
25            if target == "*" {
26                global_level = level;
27            } else {
28                config.insert(target.to_string(), level);
29            }
30        }
31        Ok(Self {
32            config,
33            global_level,
34        })
35    }
36}
37
38impl<S: Subscriber> Layer<S> for FilterLayer {
39    fn enabled(
40        &self,
41        metadata: &tracing::Metadata<'_>,
42        _ctx: tracing_subscriber::layer::Context<'_, S>,
43    ) -> bool {
44        if self.config.is_empty() {
45            return true;
46        }
47        let target = metadata.target().split("::").next().unwrap();
48        let filter = self.config.get(target).unwrap_or(&self.global_level);
49        let level = metadata.level();
50        level <= filter
51    }
52
53    fn max_level_hint(&self) -> Option<LevelFilter> {
54        self.config.values().copied().min()
55    }
56}