working example for multiple logger with flexi_logger

This commit is contained in:
jb-alvarado 2024-05-29 15:02:10 +02:00
parent 167b434e52
commit 414f2b84da
4 changed files with 246 additions and 0 deletions

37
Cargo.lock generated
View File

@ -1317,6 +1317,7 @@ dependencies = [
"derive_more",
"faccess",
"ffplayout-lib",
"flexi_logger",
"futures-util",
"home",
"jsonwebtoken",
@ -1325,6 +1326,7 @@ dependencies = [
"local-ip-address",
"log",
"once_cell",
"paris",
"parking_lot",
"path-clean",
"rand",
@ -1499,6 +1501,21 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "flexi_logger"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f248c29a6d4bc5d065c9e9068d858761a0dcd796759f7801cc14db35db23abd8"
dependencies = [
"chrono",
"glob",
"is-terminal",
"log",
"nu-ansi-term",
"regex",
"thiserror",
]
[[package]]
name = "flume"
version = "0.11.0"
@ -2021,6 +2038,17 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
[[package]]
name = "is-terminal"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
@ -2380,6 +2408,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.49.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68"
dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "num-bigint"
version = "0.4.5"

View File

@ -26,6 +26,7 @@ chrono = { version = "0.4", default-features = false, features = ["clock", "std"
clap = { version = "4.3", features = ["derive"] }
derive_more = "0.99"
faccess = "0.2"
flexi_logger = { version = "0.28", features = ["kv", "colors"] }
futures-util = { version = "0.3", default-features = false, features = ["std"] }
home = "0.5"
jsonwebtoken = "9"
@ -34,6 +35,7 @@ lexical-sort = "0.3"
local-ip-address = "0.6"
log = { version = "0.4", features = ["std", "serde", "kv", "kv_std", "kv_sval", "kv_serde"] }
once_cell = "1.18"
paris = "1.5"
parking_lot = "0.12"
path-clean = "1.0"
rand = "0.8"

View File

@ -0,0 +1,62 @@
use std::fmt;
use flexi_logger::{
filter::{LogLineFilter, LogLineWriter},
DeferredNow, FlexiLoggerError, FormatFunction, Logger,
};
use log::info;
use log::kv::Key;
use flexi_logger::writers::LogWriter;
use std::{
io::{Error, ErrorKind},
sync::{Arc, Mutex},
};
#[derive(Debug)]
enum Target {
Terminal,
File,
}
impl Target {
fn as_str(&self) -> &'static str {
match *self {
Target::Terminal => "terminal",
Target::File => "file",
}
}
}
impl fmt::Display for Target {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Target::Terminal => write!(f, "terminal"),
Target::File => write!(f, "file"),
}
}
}
pub struct Console;
impl LogLineFilter for Console {
fn write(
&self,
now: &mut DeferredNow,
record: &log::Record,
log_line_writer: &dyn LogLineWriter,
) -> std::io::Result<()> {
println!("{:?}", record.key_values().get(Key::from_str("target")));
log_line_writer.write(now, record)?;
Ok(())
}
}
fn main() -> Result<(), FlexiLoggerError> {
Logger::try_with_str("debug")?
.filter(Box::new(Console))
.start()?;
info!(target = Target::Terminal.as_str(); "info logging");
Ok(())
}

View File

@ -0,0 +1,145 @@
use log::*;
use std::io::Write;
use flexi_logger::writers::{FileLogWriter, LogWriter};
use flexi_logger::{Age, Cleanup, Criterion, DeferredNow, FileSpec, Logger, Naming};
use paris::formatter::colorize_string;
pub struct LogMailer;
impl LogWriter for LogMailer {
fn write(&self, now: &mut DeferredNow, record: &Record<'_>) -> std::io::Result<()> {
println!(
"[{}] [{:>5}] Mail logger: {:?}",
now.now().format("%Y-%m-%d %H:%M:%S"),
record.level(),
record.args()
);
Ok(())
}
fn flush(&self) -> std::io::Result<()> {
Ok(())
}
}
pub struct LogConsole;
impl LogWriter for LogConsole {
fn write(&self, now: &mut DeferredNow, record: &Record<'_>) -> std::io::Result<()> {
console_formatter(&mut std::io::stderr(), now, record)?;
println!();
Ok(())
}
fn flush(&self) -> std::io::Result<()> {
Ok(())
}
}
pub fn file_logger(to_file: bool) -> Box<dyn LogWriter> {
if to_file {
Box::new(
FileLogWriter::builder(
FileSpec::default()
.suppress_timestamp()
// .directory("/var/log")
.basename("ffplayout"),
)
.append()
.format(file_formatter)
.rotate(
Criterion::Age(Age::Day),
Naming::Timestamps,
Cleanup::KeepLogFiles(7),
)
.print_message()
.try_build()
.unwrap(),
)
} else {
Box::new(LogConsole)
}
}
// Define a macro for writing messages to the alert log and to the normal log
#[macro_use]
mod macros {
#[macro_export]
macro_rules! file_error {
($($arg:tt)*) => (
error!(target: "{File}", $($arg)*);
)
}
}
pub fn console_formatter(
w: &mut dyn Write,
now: &mut DeferredNow,
record: &Record,
) -> std::io::Result<()> {
let timestamp = colorize_string(format!(
"<dimmed>[{}]</>",
now.now().format("%Y-%m-%d %H:%M:%S%.6f")
));
let level = match record.level() {
Level::Debug => colorize_string("<bright magenta>[DEBUG]</>"),
Level::Error => colorize_string("<bright red>[ERROR]</>"),
Level::Info => colorize_string("<bright green>[ INFO]</>"),
Level::Trace => colorize_string("<bright yellow>[TRACE]</>"),
Level::Warn => colorize_string("<yellow>[ WARN]</>"),
};
write!(
w,
"{} {} {}",
timestamp,
level,
colorize_string(record.args().to_string()),
)
}
pub fn file_formatter(
w: &mut dyn Write,
now: &mut DeferredNow,
record: &Record,
) -> std::io::Result<()> {
let timestamp = format!("<dimmed>[{}]</>", now.now().format("%Y-%m-%d %H:%M:%S%.6f"));
let level = match record.level() {
Level::Debug => "<magenta>[DEBUG]</>",
Level::Error => "<red>[ERROR]</>",
Level::Info => "<green>[ INFO]</>",
Level::Trace => "<orange>[TRACE]</>",
Level::Warn => "<yellow>[ WARN]</>",
};
write!(w, "{} {} {}", timestamp, level, record.args())
}
fn main() {
let to_file = true;
Logger::try_with_str("trace")
.expect("LogSpecification String has errors")
.format(console_formatter)
.print_message()
.log_to_stderr()
.add_writer("File", file_logger(to_file))
.add_writer("Mail", Box::new(LogMailer))
.start()
.unwrap();
// Explicitly send logs to different loggers
info!(target: "{Mail}", "This logs only to Mail");
warn!(target: "{File,Mail}", "This logs to File and Mail");
error!(target: "{File}", "This logs only to file");
error!(target: "{_Default}", "This logs to console");
file_error!("This is another file log");
error!("This is a <bright red>normal error</> message");
warn!("This is a warning");
info!("This is an info message");
debug!("This is an debug message");
trace!("This is an trace message");
}