rskit_logging/
module_levels.rs1use std::collections::HashMap;
19
20use tracing_subscriber::EnvFilter;
21
22#[derive(Debug, Clone, Default)]
28pub struct ModuleLevelsConfig {
29 pub levels: HashMap<String, String>,
31}
32
33pub fn build_env_filter(base_level: &str, module_levels: &HashMap<String, String>) -> EnvFilter {
47 if let Ok(filter) = EnvFilter::try_from_default_env() {
49 return filter;
50 }
51
52 let directives = build_directives(base_level, module_levels);
53 EnvFilter::new(&directives)
54}
55
56pub fn build_directives(base_level: &str, module_levels: &HashMap<String, String>) -> String {
60 if module_levels.is_empty() {
61 return base_level.to_string();
62 }
63
64 let mut parts: Vec<String> = Vec::with_capacity(module_levels.len() + 1);
65 parts.push(base_level.to_string());
66
67 let mut entries: Vec<_> = module_levels.iter().collect();
69 entries.sort_by_key(|(k, _)| k.as_str());
70
71 for (module, level) in entries {
72 parts.push(format!("{module}={level}"));
73 }
74
75 parts.join(",")
76}
77
78#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn empty_module_levels_uses_base_only() {
86 let directives = build_directives("info", &HashMap::new());
87 assert_eq!(directives, "info");
88 }
89
90 #[test]
91 fn single_override() {
92 let mut levels = HashMap::new();
93 levels.insert("sqlx".to_string(), "warn".to_string());
94 let directives = build_directives("info", &levels);
95 assert_eq!(directives, "info,sqlx=warn");
96 }
97
98 #[test]
99 fn multiple_overrides_sorted() {
100 let mut levels = HashMap::new();
101 levels.insert("sqlx".to_string(), "warn".to_string());
102 levels.insert("rdkafka".to_string(), "off".to_string());
103 levels.insert("hyper".to_string(), "error".to_string());
104 let directives = build_directives("debug", &levels);
105 assert_eq!(directives, "debug,hyper=error,rdkafka=off,sqlx=warn");
106 }
107
108 #[test]
109 fn base_level_respected() {
110 let levels = HashMap::new();
111 let directives = build_directives("trace", &levels);
112 assert_eq!(directives, "trace");
113 }
114
115 #[test]
116 fn build_env_filter_creates_valid_filter() {
117 let mut levels = HashMap::new();
118 levels.insert("sqlx".to_string(), "warn".to_string());
119 let _filter = build_env_filter("info", &levels);
121 }
122
123 #[test]
124 fn module_levels_config_default_is_empty() {
125 let cfg = ModuleLevelsConfig::default();
126 assert!(cfg.levels.is_empty());
127 }
128}