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::datastore::config::DatastoreConfig;
10use crate::datastore_logger::DatastoreLogger;
11use crate::syslog_logger::SyslogLogger;
12
13mod console_logger;
14mod datastore;
15mod datastore_logger;
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 console, syslog, and Datastore
27pub struct Logger {
28    console: ConsoleLogger,
29    syslog: SyslogLogger,
30    datastore: DatastoreLogger,
31    allowed_targets: Vec<String>,
32}
33
34impl Logger {
35    /// Initializes the logger with the given configuration
36    ///
37    /// # Arguments
38    /// * `logger_config` - The logger configuration
39    pub fn init(logger_config: LoggerConfig) {
40        let LoggerConfig {
41            console,
42            syslog,
43            datastore,
44            allowed_targets,
45        } = logger_config;
46
47        let env_log_level = std::env::var("LOG_LEVEL").unwrap_or("trace".to_string());
48        let level_filter = LevelFilter::from_str(&env_log_level).unwrap_or(LevelFilter::Trace);
49        if level_filter.to_level().is_some() {
50            let allowed_targets = allowed_targets.into_iter().map(str::to_lowercase).collect();
51            log::set_boxed_logger(Box::new(Logger {
52                console: ConsoleLogger::new(console),
53                syslog: SyslogLogger::new(syslog),
54                datastore: DatastoreLogger::new(datastore),
55                allowed_targets,
56            }))
57            .unwrap_or_default();
58        }
59        log::set_max_level(level_filter);
60    }
61}
62
63impl log::Log for Logger {
64    fn enabled(&self, metadata: &log::Metadata) -> bool {
65        !metadata.target().starts_with("nullnet_liblogging")
66            && (self.syslog.enabled(metadata)
67                || self.console.enabled(metadata)
68                || self.datastore.enabled(metadata))
69    }
70
71    fn log(&self, record: &log::Record) {
72        if self.enabled(record.metadata()) {
73            let target = record.target().to_lowercase();
74            if DEFAULT_ALLOWED_TARGETS
75                .iter()
76                .any(|s| target.starts_with(s))
77                || self.allowed_targets.iter().any(|s| target.starts_with(s))
78            {
79                self.syslog.log(record);
80                self.console.log(record);
81                self.datastore.log(record);
82            }
83        }
84    }
85
86    fn flush(&self) {
87        self.syslog.flush();
88        self.console.flush();
89        self.datastore.flush();
90    }
91}
92
93/// Logger configuration
94pub struct LoggerConfig {
95    console: bool,
96    syslog: bool,
97    datastore: Option<DatastoreConfig>,
98    allowed_targets: Vec<&'static str>,
99}
100
101impl LoggerConfig {
102    /// Creates a new logger configuration
103    ///
104    /// # Arguments
105    /// * `console` - Whether to log to console
106    /// * `syslog` - Whether to log to syslog
107    /// * `datastore` - Datastore logging configuration (use `None` to disable logging to Datastore)
108    /// * `allowed_targets` - The list of allowed targets.<br>
109    ///   By default, only logs from `nullnet*`, `appguard*`, and `wallguard*` will be emitted.<br>
110    ///   Use this parameter to specify additional targets
111    ///   (e.g., specifying "serde" will emit logs for all targets whose name is in the form `serde*`).
112    #[must_use]
113    pub fn new(
114        console: bool,
115        syslog: bool,
116        datastore: Option<DatastoreConfig>,
117        allowed_targets: Vec<&'static str>,
118    ) -> Self {
119        Self {
120            console,
121            syslog,
122            datastore,
123            allowed_targets,
124        }
125    }
126}