use crate::*;
use std::{cell::RefCell, collections::HashMap, fs};
pub struct LoggerBuilder {
mod_path: String,
fn_name: String,
level: Level,
handlers: RefCell<HashMap<Handler, Box<dyn HandlerTrait>>>,
}
impl LoggerBuilder {
pub(super) fn create(mod_path: String) -> Self {
LoggerBuilder {
mod_path,
fn_name: String::new(),
level: Level::default(),
handlers: RefCell::new(HashMap::new()),
}
}
pub fn add_console_handler(self) -> Self {
self.add_handler_with(Handler::Console, None, None, None, None)
}
pub fn add_console_handler_with(
self,
format_type: FormatType,
custom_formatter: Option<Box<dyn FormatTrait>>,
) -> Self {
self.add_handler_with(
Handler::Console,
None,
None,
Some(format_type),
custom_formatter,
)
}
pub fn add_econsole_handler(self) -> Self {
self.add_handler_with(Handler::EConsole, None, None, None, None)
}
pub fn add_econsole_handler_with(
self,
format_type: FormatType,
custom_formatter: Option<Box<dyn FormatTrait>>,
) -> Self {
self.add_handler_with(
Handler::EConsole,
None,
None,
Some(format_type),
custom_formatter,
)
}
pub fn add_custom_handler(self, label: &str, custom_handler: Box<dyn HandlerTrait>) -> Self {
self.add_handler_with(
Handler::Custom(label.to_string()),
Some(custom_handler),
None,
None,
None,
)
}
pub fn add_custom_handler_with(
self,
label: &str,
custom_handler: Box<dyn HandlerTrait>,
format_type: FormatType,
custom_formatter: Option<Box<dyn FormatTrait>>,
) -> Self {
self.add_handler_with(
Handler::Custom(label.to_string()),
Some(custom_handler),
None,
Some(format_type),
custom_formatter,
)
}
pub fn add_file_handler(self, filename: &str) -> Self {
self.add_handler_with(Handler::File, None, Some(filename), None, None)
}
pub fn add_file_handler_with(
self,
filename: &str,
format_type: FormatType,
custom_formatter: Option<Box<dyn FormatTrait>>,
) -> Self {
self.add_handler_with(
Handler::File,
None,
Some(filename),
Some(format_type),
custom_formatter,
)
}
fn add_handler_with(
mut self,
handler: Handler,
custom_handler: Option<Box<dyn HandlerTrait>>,
filename: Option<&str>,
format_type: Option<FormatType>,
custom_formatter: Option<Box<dyn FormatTrait>>,
) -> Self {
let name = filename.unwrap_or(&self.mod_path);
let mut h: Box<dyn HandlerTrait> = match handler {
Handler::Console => {
Box::new(ConsoleHandler::create(ConsoleType::StdOut.as_str()).unwrap())
}
Handler::EConsole => {
Box::new(ConsoleHandler::create(ConsoleType::StdErr.as_str()).unwrap())
}
Handler::File => Box::new(FileHandler::create(name).unwrap()),
Handler::PConsole => {
Box::new(ConsoleHandler::create(ConsoleType::Production.as_str()).unwrap())
}
Handler::String => Box::new(StringHandler::create(name).unwrap()),
Handler::Custom(_) => custom_handler.unwrap(),
};
if let Some(f) = format_type {
h.set_formatter(match f {
FormatType::Iso8601 => f.create(None),
FormatType::Simple => f.create(None),
FormatType::UnixTimestamp => f.create(None),
FormatType::Custom => f.create(custom_formatter),
});
}
let map = self.handlers.get_mut();
map.insert(handler, h);
self
}
pub fn add_pconsole_handler(self) -> Self {
self.add_handler_with(Handler::PConsole, None, None, None, None)
}
pub fn add_pconsole_handler_with(
self,
format_type: FormatType,
custom_formatter: Option<Box<dyn FormatTrait>>,
) -> Self {
self.add_handler_with(
Handler::PConsole,
None,
None,
Some(format_type),
custom_formatter,
)
}
pub fn add_string_handler(self) -> Self {
self.add_handler_with(Handler::String, None, None, None, None)
}
pub fn add_string_handler_with(
self,
format_type: FormatType,
custom_formatter: Option<Box<dyn FormatTrait>>,
) -> Self {
self.add_handler_with(
Handler::String,
None,
None,
Some(format_type),
custom_formatter,
)
}
pub fn build(self) -> Logger {
Logger {
mod_path: self.mod_path.clone(),
fn_name: self.fn_name.clone(),
level: self.level,
handlers: self.handlers,
}
}
pub fn remove_file(self, filename: &str) -> Self {
let _ = fs::remove_file(filename).is_err();
self
}
pub fn set_fn_name(mut self, fn_name: &str) -> Self {
self.fn_name = fn_name.to_string();
self
}
pub fn set_level(mut self, level: Level) -> Self {
self.level = level;
self
}
}
#[cfg(test)]
mod tests {
use crate::*;
use regex::Regex;
use std::io::{Result, Stdout, Write, stdout};
#[test]
fn temp() -> Result<()> {
let msg = "arguments";
let mut w = stdout();
writeln!(&mut w)?;
writeln!(&mut w, "test")?;
writeln!(&mut w, "formatted {}", msg)?;
Ok(())
}
#[test]
fn add_console_handler() {
let expected = "flogging::logger::builder::tests->add_console_handler [INFO ] We begin!
flogging::logger::builder::tests->add_console_handler [WARNING] Need more tests.
"
.to_string();
let mut log = Logger::builder(module_path!())
.add_console_handler()
.set_fn_name("add_console_handler")
.build();
let h = log.get_handler(crate::Handler::Console).unwrap();
h.set_test_mode(true);
log.info("We begin!");
log.warning("Need more tests.");
let h = log.get_handler(crate::Handler::Console).unwrap();
let buf = h.get_log();
assert_eq!(expected, buf);
}
#[test]
fn add_console_handler_with() {
let re_str =
"^(?:\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{9}\\+\\d{2}:\\d{2}) flogging::logger::builder::tests->add_console_handler_with \\[INFO ] We begin!
(?:\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{9}\\+\\d{2}:\\d{2}) flogging::logger::builder::tests->add_console_handler_with \\[WARNING] Need more tests.
$";
let re = Regex::new(re_str).unwrap();
let mut log = Logger::builder(module_path!())
.add_console_handler_with(FormatType::Iso8601, None)
.set_fn_name("add_console_handler_with")
.build();
let h = log.get_handler(crate::Handler::Console).unwrap();
h.set_test_mode(true);
log.info("We begin!");
log.warning("Need more tests.");
let h = log.get_handler(crate::Handler::Console).unwrap();
let result = h.get_log();
println!("{result}");
assert!(re.is_match(&result));
}
#[test]
fn add_econsole_handler() {
let mut log = Logger::builder(module_path!())
.add_econsole_handler()
.set_fn_name("add_econsole_handler")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_econsole_handler_with() {
let mut log = Logger::builder(module_path!())
.add_econsole_handler_with(FormatType::Iso8601, None)
.set_fn_name("add_econsole_handler_with")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_custom_handler() {
let mut log = Logger::builder(module_path!())
.add_custom_handler(
"Console",
Box::new(ConsoleHandler::create(ConsoleType::StdOut.as_str()).unwrap()),
)
.set_fn_name("add_custom_handler")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_custom_handler_with() {
let mut log = Logger::builder(module_path!())
.add_custom_handler_with(
"Console",
Box::new(ConsoleHandler::create(ConsoleType::StdOut.as_str()).unwrap()),
FormatType::Custom,
Some(Box::new(MockFormatter::new())),
)
.set_fn_name("add_custom_handler_with")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_file_handler() {
let mut log = Logger::builder(module_path!())
.add_file_handler("test_logs/add_file_handler.log")
.set_fn_name("add_file_handler")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_file_handler_with() {
let mut log = Logger::builder(module_path!())
.add_file_handler_with(
"test_logs/add_file_handler_with.log",
crate::FormatType::UnixTimestamp,
None,
)
.set_fn_name("add_file_handler_with")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_pconsole_handler() {
let mut log = Logger::builder(module_path!())
.add_pconsole_handler()
.set_fn_name("add_pconsole_handler")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_pconsole_handler_with() {
let mut log = Logger::builder(module_path!())
.add_pconsole_handler_with(FormatType::Iso8601, None)
.set_fn_name("add_pconsole_handler_with")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_string_handler() {
let mut log = Logger::builder(module_path!())
.add_string_handler()
.set_fn_name("add_string_handler")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn add_string_handler_with() {
let mut log = Logger::builder(module_path!())
.add_string_handler_with(crate::FormatType::Simple, None)
.set_fn_name("add_string_handler_with")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
#[test]
fn remove_file() {
let mut log = Logger::builder(module_path!())
.remove_file("test_logs/remove_file.log")
.add_file_handler("test_logs/remove_file.log")
.set_fn_name("add_file_handler")
.build();
log.info("We begin!");
log.warning("Need more tests.");
}
}