nullnet_liblogging/
lib.rs

1#![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
23/// Logger implementation that logs to both syslog and console
24pub struct Logger {
25    syslog: SyslogLogger,
26    console: ConsoleLogger,
27    allowed_targets: Vec<String>,
28}
29
30impl Logger {
31    /// Initializes the logger with the given syslog server, process name, and allowed targets
32    ///
33    /// # Arguments
34    /// * `syslog_server` - The syslog server to log to
35    /// * `process_name` - The name of the process
36    /// * `allowed_targets` - The list of allowed targets; if any are specified,
37    ///   only logs from targets starting with one of these entries will be printed.
38    pub fn init(
39        syslog_server: 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: SyslogLogger::new(syslog_server, 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.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            self.syslog.log(record);
71            self.console.log(record);
72        }
73    }
74
75    fn flush(&self) {
76        self.syslog.flush();
77        self.console.flush();
78    }
79}