use std::sync::Mutex;
pub use ::slog;
use format::LogFormat;
use once_cell::sync::Lazy;
use slog::{o, Drain, FnValue, Logger, PushFnValue, Record};
pub static LOGGER: Lazy<slog::Logger> = Lazy::new(|| new_logger());
pub fn new_logger() -> Logger {
match LogFormat::from_env() {
LogFormat::PlainText => {
let decorator = slog_term::PlainDecorator::new(std::io::stdout());
let drain = slog_term::FullFormat::new(decorator).build().fuse();
let drain = slog_async::Async::new(drain).chan_size(1000).build().fuse();
let drain = Mutex::new(drain).map(slog::Fuse);
slog::Logger::root(drain, o!())
}
LogFormat::Json => {
let drain = slog_json::Json::new(std::io::stdout()).build().fuse();
let drain = slog_async::Async::new(drain).chan_size(1000).build().fuse();
let drain = Mutex::new(drain).map(slog::Fuse);
slog::Logger::root(
drain,
o!(
"ts" => PushFnValue(move |_: &Record, ser| {
ser.emit(chrono::Local::now().to_rfc3339())
}),
"lvl" => FnValue(move |rec: &Record| {
rec.level().as_short_str()
}),
"msg" => PushFnValue(move |rec: &Record, ser| {
ser.emit(rec.msg())
}),
),
)
}
}
}
#[macro_export]
macro_rules! trace(
(#$tag:expr, $($args:tt)+) => {
$crate::slog::trace!($crate::LOGGER, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
$crate::slog::trace!($crate::LOGGER, "", $($args)+)
};
);
#[macro_export]
macro_rules! debug(
(#$tag:expr, $($args:tt)+) => {
$crate::slog::debug!($crate::LOGGER, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
$crate::slog::debug!($crate::LOGGER, "", $($args)+)
};
);
#[macro_export]
macro_rules! info(
(#$tag:expr, $($args:tt)+) => {
$crate::slog::info!($crate::LOGGER, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
$crate::slog::info!($crate::LOGGER, "", $($args)+)
};
);
#[macro_export]
macro_rules! warn(
(#$tag:expr, $($args:tt)+) => {
$crate::slog::warn!($crate::LOGGER, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
$crate::slog::warn!($crate::LOGGER, "", $($args)+)
};
);
#[macro_export]
macro_rules! error(
(#$tag:expr, $($args:tt)+) => {
$crate::slog::error!($crate::LOGGER, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
$crate::slog::error!($crate::LOGGER, "", $($args)+)
};
);
#[macro_export]
macro_rules! crit(
(#$tag:expr, $($args:tt)+) => {
$crate::slog::crit!($crate::LOGGER, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
$crate::slog::crit!($crate::LOGGER, "", $($args)+)
};
);
mod format {
use std::env;
#[derive(Copy, Clone)]
pub(crate) enum LogFormat {
PlainText,
Json,
}
impl Default for LogFormat {
fn default() -> Self {
Self::Json
}
}
impl<S: AsRef<str>> From<S> for LogFormat {
fn from(s: S) -> Self {
match s.as_ref() {
"plain" => Self::PlainText,
"json" => Self::Json,
"" => Default::default(),
_ => panic!("Unrecognized {} value: '{}'", Self::ENV_NAME, s.as_ref()),
}
}
}
impl LogFormat {
const ENV_NAME: &'static str = "RUST_LOG_FORMAT";
pub(crate) fn from_env() -> Self {
Self::from(env::var(Self::ENV_NAME).ok().unwrap_or_default())
}
}
}