turbopack_trace_utils/
filter_layer.rs1use 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}