pub mod console_type;
use crate::*;
use console_type::ConsoleType;
use std::{
fmt,
io::{self, Error, Write},
};
#[derive(Debug, Default)]
pub struct ConsoleHandler {
console_type: ConsoleType,
formatter: Formatter,
writer: Option<Vec<u8>>,
}
impl ConsoleHandler {
fn _create(console_type: ConsoleType) -> Self {
ConsoleHandler {
console_type,
formatter: FormatType::Simple.create(None),
writer: None,
}
}
fn log(&self) -> String {
if let Some(w) = self.writer.to_owned() {
String::from_utf8(w).unwrap()
} else {
String::new()
}
}
}
impl fmt::Display for ConsoleHandler {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.formatter.fmt(f)
}
}
impl HandlerTrait for ConsoleHandler {
fn create(console_type: &str) -> Result<Self, Error>
where
Self: Sized,
{
Ok(ConsoleHandler::_create(console_type.parse().unwrap()))
}
fn close(&mut self) {
if self.writer.is_some() {
self.writer = None;
}
}
fn flush(&mut self) {
if let Some(w) = self.writer.as_mut() {
w.clear()
};
}
fn get_formatter(&self) -> Formatter {
self.formatter.clone()
}
fn get_log(&self) -> String {
self.log()
}
fn is_open(&self) -> bool {
true
}
fn publish(&mut self, log_entry: &LogEntry) {
match self.writer.as_mut() {
Some(w) => {
let _ = match self.console_type {
ConsoleType::StdOut => writeln!(w, "{}", self.formatter.format(log_entry)),
ConsoleType::StdErr => writeln!(w, "{}", self.formatter.format(log_entry)),
ConsoleType::Production => production_test(w, &self.formatter, log_entry),
};
}
None => match self.console_type {
ConsoleType::StdOut => println!("{}", self.formatter.format(log_entry)),
ConsoleType::StdErr => eprintln!("{}", self.formatter.format(log_entry)),
ConsoleType::Production => production(&self.formatter, log_entry),
},
}
}
fn set_formatter(&mut self, formatter: Formatter) {
self.formatter = formatter;
}
fn set_test_mode(&mut self, state: bool) {
if state {
self.writer = Some(Vec::new());
} else {
self.writer = None;
}
}
}
fn production(formatter: &Formatter, log_entry: &LogEntry) {
if log_entry.level() == Level::INFO {
println!("{}", log_entry.message());
} else {
eprintln!("{}", formatter.format(log_entry));
}
}
fn production_test(
writer: &mut Vec<u8>,
formatter: &Formatter,
log_entry: &LogEntry,
) -> io::Result<()> {
if log_entry.level() == Level::INFO {
writeln!(writer, "{}", log_entry.message())?;
} else {
writeln!(writer, "{}", formatter.format(log_entry))?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn stdout_handler() {
let mut log = Logger::console_logger(module_path!());
log.info("trait methods");
log.warning("The sky is falling!");
let handler = log.get_handler(crate::Handler::Console).unwrap();
handler.set_test_mode(false);
assert!(handler.is_open());
assert_eq!(
handler.get_formatter().to_string(),
"dt_fmt: \"\" - fmt_string: \"{mod_path}->{fn_name} [{level:7}] {message}\""
.to_string()
);
assert_eq!(handler.get_log(), "".to_string());
handler.flush();
handler.close();
}
#[test]
fn stdout_handler_test_mode() {
let expected = "flogging::handlers::console_handler::tests-> [INFO ] trait methods
flogging::handlers::console_handler::tests-> [WARNING] The sky is falling!
"
.to_string();
let mut log = Logger::console_logger(module_path!());
let h = log.get_handler(crate::Handler::Console).unwrap();
h.set_test_mode(true);
assert!(h.is_open());
assert_eq!(
h.get_formatter().to_string(),
"dt_fmt: \"\" - fmt_string: \"{mod_path}->{fn_name} [{level:7}] {message}\""
.to_string()
);
log.info("trait methods");
log.warning("The sky is falling!");
let h = log.get_handler(crate::Handler::Console).unwrap();
let buf = h.get_log();
assert_eq!(expected, buf);
h.flush();
h.close();
}
#[test]
fn stderr_handler() {
let mut log = Logger::econsole_logger(module_path!());
log.info("trait methods");
log.warning("The sky is falling!");
let handler = log.get_handler(crate::Handler::EConsole).unwrap();
handler.set_test_mode(false);
assert!(handler.is_open());
assert_eq!(
handler.get_formatter().to_string(),
"dt_fmt: \"\" - fmt_string: \"{mod_path}->{fn_name} [{level:7}] {message}\""
.to_string()
);
assert_eq!(handler.get_log(), "".to_string());
handler.flush();
handler.close();
}
#[test]
fn stderr_handler_test_mode() {
let expected = "flogging::handlers::console_handler::tests-> [INFO ] trait methods
flogging::handlers::console_handler::tests-> [WARNING] The sky is falling!\n"
.to_string();
let mut log = Logger::econsole_logger(module_path!());
let h = log.get_handler(crate::Handler::EConsole).unwrap();
h.set_test_mode(true);
assert!(h.is_open());
assert_eq!(
h.get_formatter().to_string(),
"dt_fmt: \"\" - fmt_string: \"{mod_path}->{fn_name} [{level:7}] {message}\""
.to_string()
);
log.info("trait methods");
log.warning("The sky is falling!");
let h = log.get_handler(crate::Handler::EConsole).unwrap();
let buf = h.get_log();
assert_eq!(expected, buf);
h.flush();
h.close();
}
#[test]
fn production_handler() {
let mut log = Logger::pconsole_logger(module_path!());
log.info("trait methods");
log.warning("The sky is falling!");
let handler = log.get_handler(crate::Handler::PConsole).unwrap();
handler.set_test_mode(false);
assert!(handler.is_open());
assert_eq!(
handler.get_formatter().to_string(),
"dt_fmt: \"\" - fmt_string: \"{mod_path}->{fn_name} [{level:7}] {message}\""
.to_string()
);
assert_eq!(handler.get_log(), "".to_string());
handler.flush();
handler.close();
}
#[test]
fn production_handler_test_mode() {
let expected = "trait methods
flogging::handlers::console_handler::tests-> [WARNING] The sky is falling!\n"
.to_string();
let mut log = Logger::pconsole_logger(module_path!());
let h = log.get_handler(crate::Handler::PConsole).unwrap();
h.set_test_mode(true);
assert!(h.is_open());
assert_eq!(
h.get_formatter().to_string(),
"dt_fmt: \"\" - fmt_string: \"{mod_path}->{fn_name} [{level:7}] {message}\""
.to_string()
);
log.info("trait methods");
log.warning("The sky is falling!");
let h = log.get_handler(crate::Handler::PConsole).unwrap();
let buf = h.get_log();
assert_eq!(expected, buf);
h.flush();
h.close();
}
}