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
8pub use error::{Error, ErrorHandler, Location};
9
10use crate::console_logger::ConsoleLogger;
11pub use crate::syslog_logger::SyslogEndpoint;
12use crate::syslog_logger::SyslogLogger;
13
14mod console_logger;
15mod error;
16mod syslog_logger;
17
18static DEFAULT_ALLOWED_TARGETS: once_cell::sync::Lazy<Vec<String>> =
19    once_cell::sync::Lazy::new(|| {
20        vec!["nullnet", "appguard", "wallguard"]
21            .into_iter()
22            .map(str::to_lowercase)
23            .collect()
24    });
25
26/// Logger implementation that logs to both syslog and console
27pub struct Logger {
28    syslog: SyslogLogger,
29    console: ConsoleLogger,
30    allowed_targets: Vec<String>,
31}
32
33impl Logger {
34    /// Initializes the logger with the given syslog server, process name, and allowed targets
35    ///
36    /// # Arguments
37    /// * `syslog_server` - The syslog server to log to
38    /// * `process_name` - The name of the process
39    /// * `allowed_targets` - The list of allowed targets; if any are specified,
40    ///   only logs from targets starting with one of these entries will be printed.
41    pub fn init(
42        syslog_server: SyslogEndpoint,
43        process_name: &str,
44        allowed_targets: Vec<&'static str>,
45    ) {
46        let env_log_level = std::env::var("LOG_LEVEL").unwrap_or("trace".to_string());
47        let level_filter = LevelFilter::from_str(&env_log_level).unwrap_or(LevelFilter::Trace);
48        if level_filter.to_level().is_some() {
49            let allowed_targets = allowed_targets.into_iter().map(str::to_lowercase).collect();
50            log::set_boxed_logger(Box::new(Logger {
51                syslog: SyslogLogger::new(syslog_server, process_name),
52                console: ConsoleLogger::new(),
53                allowed_targets,
54            }))
55            .unwrap_or_default();
56        }
57        log::set_max_level(level_filter);
58    }
59}
60
61impl log::Log for Logger {
62    fn enabled(&self, metadata: &log::Metadata) -> bool {
63        self.syslog.enabled(metadata) || self.console.enabled(metadata)
64    }
65
66    fn log(&self, record: &log::Record) {
67        let target = record.target().to_lowercase();
68        if DEFAULT_ALLOWED_TARGETS
69            .iter()
70            .any(|s| target.starts_with(s))
71            || self.allowed_targets.iter().any(|s| target.starts_with(s))
72        {
73            self.syslog.log(record);
74            self.console.log(record);
75        }
76    }
77
78    fn flush(&self) {
79        self.syslog.flush();
80        self.console.flush();
81    }
82}