nullnet_liblogging/
lib.rs1#![doc = include_str!("../README.md")]
2
3use std::iter::{IntoIterator, Iterator};
4use std::str::FromStr;
5
6use log::LevelFilter;
7
8use crate::console_logger::ConsoleLogger;
9pub use crate::syslog_logger::SyslogEndpoint;
10use crate::syslog_logger::SyslogLogger;
11
12mod console_logger;
13mod syslog_logger;
14
15static DEFAULT_ALLOWED_TARGETS: once_cell::sync::Lazy<Vec<String>> =
16 once_cell::sync::Lazy::new(|| {
17 vec!["nullnet", "appguard", "wallguard"]
18 .into_iter()
19 .map(str::to_lowercase)
20 .collect()
21 });
22
23pub struct Logger {
25 syslog: Option<SyslogLogger>,
26 console: ConsoleLogger,
27 allowed_targets: Vec<String>,
28}
29
30impl Logger {
31 pub fn init(
39 syslog_endpoint: Option<SyslogEndpoint>,
40 process_name: &str,
41 allowed_targets: Vec<&'static str>,
42 ) {
43 let env_log_level = std::env::var("LOG_LEVEL").unwrap_or("trace".to_string());
44 let level_filter = LevelFilter::from_str(&env_log_level).unwrap_or(LevelFilter::Trace);
45 if level_filter.to_level().is_some() {
46 let allowed_targets = allowed_targets.into_iter().map(str::to_lowercase).collect();
47 log::set_boxed_logger(Box::new(Logger {
48 syslog: syslog_endpoint.map(|s| SyslogLogger::new(s, process_name)),
49 console: ConsoleLogger::new(),
50 allowed_targets,
51 }))
52 .unwrap_or_default();
53 }
54 log::set_max_level(level_filter);
55 }
56}
57
58impl log::Log for Logger {
59 fn enabled(&self, metadata: &log::Metadata) -> bool {
60 self.syslog.as_ref().is_some_and(|s| s.enabled(metadata)) || self.console.enabled(metadata)
61 }
62
63 fn log(&self, record: &log::Record) {
64 let target = record.target().to_lowercase();
65 if DEFAULT_ALLOWED_TARGETS
66 .iter()
67 .any(|s| target.starts_with(s))
68 || self.allowed_targets.iter().any(|s| target.starts_with(s))
69 {
70 if let Some(s) = self.syslog.as_ref() {
71 s.log(record);
72 }
73 self.console.log(record);
74 }
75 }
76
77 fn flush(&self) {
78 if let Some(s) = self.syslog.as_ref() {
79 s.flush();
80 }
81 self.console.flush();
82 }
83}