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::datastore::config::{DatastoreConfig, ServerKind};
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: std::sync::LazyLock<Vec<String>> = std::sync::LazyLock::new(|| {
19 vec!["nullnet", "appguard", "wallguard"]
20 .into_iter()
21 .map(str::to_lowercase)
22 .collect()
23});
24
25pub struct Logger {
27 console: ConsoleLogger,
28 syslog: SyslogLogger,
29 datastore: DatastoreLogger,
30 allowed_targets: Vec<String>,
31}
32
33impl Logger {
34 pub fn init(logger_config: LoggerConfig) {
39 let LoggerConfig {
40 console,
41 syslog,
42 datastore,
43 allowed_targets,
44 } = logger_config;
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 console: ConsoleLogger::new(console),
52 syslog: SyslogLogger::new(syslog),
53 datastore: DatastoreLogger::new(datastore),
54 allowed_targets,
55 }))
56 .unwrap_or_default();
57 }
58 log::set_max_level(level_filter);
59 }
60}
61
62impl log::Log for Logger {
63 fn enabled(&self, metadata: &log::Metadata) -> bool {
64 !metadata.target().starts_with("nullnet_liblogging")
65 && (self.syslog.enabled(metadata)
66 || self.console.enabled(metadata)
67 || self.datastore.enabled(metadata))
68 }
69
70 fn log(&self, record: &log::Record) {
71 if self.enabled(record.metadata()) {
72 let target = record.target().to_lowercase();
73 if DEFAULT_ALLOWED_TARGETS
74 .iter()
75 .any(|s| target.starts_with(s))
76 || self.allowed_targets.iter().any(|s| target.starts_with(s))
77 {
78 self.syslog.log(record);
79 self.console.log(record);
80 self.datastore.log(record);
81 }
82 }
83 }
84
85 fn flush(&self) {
86 self.syslog.flush();
87 self.console.flush();
88 self.datastore.flush();
89 }
90}
91
92pub struct LoggerConfig {
94 console: bool,
95 syslog: bool,
96 datastore: Option<DatastoreConfig>,
97 allowed_targets: Vec<&'static str>,
98}
99
100impl LoggerConfig {
101 #[must_use]
112 pub fn new(
113 console: bool,
114 syslog: bool,
115 datastore: Option<DatastoreConfig>,
116 allowed_targets: Vec<&'static str>,
117 ) -> Self {
118 Self {
119 console,
120 syslog,
121 datastore,
122 allowed_targets,
123 }
124 }
125}