#[macro_export]
macro_rules! flush {
() => {{
$crate::LOG_SENDER.try_send($crate::LogMessage::Flush).expect("Failed to send flush message");
}};
}
#[macro_export]
macro_rules! log_with_level {
($level:expr, $topic:expr; $fmt:expr, $($arg:expr),* ; $($key:ident = $value:expr),+ $(,)?) => {{
$crate::log_fn_json_v2!($level, $topic; $fmt, $($arg),*; $($key = $value),+);
}};
($level:expr, $topic:expr; $msg:expr; $($key:ident = $value:expr),+ $(,)?) => {{
$crate::log_fn_json_v2!($level, $topic; $msg; $($key = $value),+);
}};
($level:expr, $topic:expr; $($key:ident = $value:expr),+ $(,)?) => {{
$crate::log_fn_json_v2!($level, $topic; ""; $($key = $value),+);
}};
($level:expr, $topic:expr; $fmt:expr, $($arg:expr),* $(,)?) => {{
$crate::log_fn_json_v2!($level, $topic; $fmt, $($arg),*);
}};
($level:expr, $topic:expr; $msg:expr) => {{
$crate::log_fn_json_v2!($level, $topic; $msg);
}};
($level:expr, $topic:expr) => {{
$crate::log_fn_json_v2!($level, $topic; "");
}};
($level:expr, $key:ident = $value:expr $(,)?) => {{
$crate::log_fn_json_v2!($level, $key = $value);
}};
($level:expr, $($key:ident = $value:expr),+ $(,)?) => {{
$crate::log_fn_json_v2!($level, $($key = $value),+);
}};
}
#[deprecated(since = "0.3.0", note = "Use flash_trace_ct! instead")]
#[macro_export]
macro_rules! flash_trace {
( $( $key:ident = $value:expr ),+ $(,)? ) => {
$crate::log_with_level!($crate::LogLevel::Trace, ""; $( $key = $value ),+ );
};
( $($args:tt)* ) => {
$crate::log_with_level!($crate::LogLevel::Trace, $($args)* );
};
}
#[deprecated(since = "0.3.0", note = "Use flash_debug_ct! instead")]
#[macro_export]
macro_rules! flash_debug {
( $( $key:ident = $value:expr ),+ $(,)? ) => {
$crate::log_with_level!($crate::LogLevel::Debug, ""; $( $key = $value ),+ )
};
( $($args:tt)* ) => {
$crate::log_with_level!($crate::LogLevel::Debug, $($args)* )
};
}
#[deprecated(since = "0.3.0", note = "Use flash_info_ct! instead")]
#[macro_export]
macro_rules! flash_info {
( $( $key:ident = $value:expr ),+ $(,)? ) => {
$crate::log_with_level!($crate::LogLevel::Info, ""; $( $key = $value ),+ );
};
( $($args:tt)* ) => {
$crate::log_with_level!($crate::LogLevel::Info, $($args)* );
};
}
#[deprecated(since = "0.3.0", note = "Use flash_warn_ct! instead")]
#[macro_export]
macro_rules! flash_warn {
( $( $key:ident = $value:expr ),+ $(,)? ) => {
$crate::log_with_level!($crate::LogLevel::Warn, ""; $( $key = $value ),+ )
};
( $($args:tt)* ) => {
$crate::log_with_level!($crate::LogLevel::Warn, $($args)* )
};
}
#[deprecated(since = "0.3.0", note = "Use flash_error_ct! instead")]
#[macro_export]
macro_rules! flash_error {
( $( $key:ident = $value:expr ),+ $(,)? ) => {
$crate::log_with_level!($crate::LogLevel::Error, ""; $( $key = $value ),+ )
};
( $($args:tt)* ) => {
$crate::log_with_level!($crate::LogLevel::Error, $($args)* )
};
}
#[macro_export]
macro_rules! log_fn_json_v2 {
($level:expr, $topic:expr; $fmt:expr, $($arg:expr),*; $($key:ident = $value:expr),+ $(,)?) => {{
if $level <= $crate::LogLevel::from_usize($crate::MAX_LOG_LEVEL.load(std::sync::atomic::Ordering::Relaxed)).expect("Invalid log level") {
let func = move || {
let unixnano = $crate::get_unix_nano();
let include_unixnano = $crate::logger::INCLUDE_UNIXNANO.load(std::sync::atomic::Ordering::Relaxed);
let json_obj = $crate::serde_json::json!({
$(
stringify!($key): $value,
)+
});
let timezone = $crate::TIMEZONE.load(std::sync::atomic::Ordering::Relaxed);
let (date, time) = $crate::convert_unix_nano_to_date_and_time(unixnano, timezone);
let json_msg = match include_unixnano {
false => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic,
"data": json_obj,
"message": format!($fmt, $($arg),*),
}),
true => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic,
"data": json_obj,
"message": format!($fmt, $($arg),*),
"unixnano": unixnano,
}),
};
json_msg.to_string() + "\n"
};
$crate::LOG_SENDER.try_send($crate::LogMessage::LazyMessage($crate::LazyMessage::new(func))).expect("Failed to send log message");
}
}};
($level:expr, $topic:expr; $msg:expr; $($key:ident = $value:expr),+ $(,)?) => {{
if $level <= $crate::LogLevel::from_usize($crate::MAX_LOG_LEVEL.load(std::sync::atomic::Ordering::Relaxed)).expect("Invalid log level") {
let func = move || {
let unixnano = $crate::get_unix_nano();
let include_unixnano = $crate::logger::INCLUDE_UNIXNANO.load(std::sync::atomic::Ordering::Relaxed);
let json_obj = $crate::serde_json::json!({
$(
stringify!($key): $value,
)+
});
let timezone = $crate::TIMEZONE.load(std::sync::atomic::Ordering::Relaxed);
let (date, time) = $crate::convert_unix_nano_to_date_and_time(unixnano, timezone);
let json_msg = match include_unixnano {
false => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic,
"data": json_obj,
"message": $msg,
}),
true => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic,
"data": json_obj,
"message": $msg,
"unixnano": unixnano,
}),
};
json_msg.to_string() + "\n"
};
$crate::LOG_SENDER.try_send($crate::LogMessage::LazyMessage($crate::LazyMessage::new(func))).expect("Failed to send log message");
}
}};
($level:expr, $topic:expr; $fmt:expr, $($arg:expr),* $(,)?) => {{
if $level <= $crate::LogLevel::from_usize($crate::MAX_LOG_LEVEL.load(std::sync::atomic::Ordering::Relaxed)).expect("Invalid log level") {
let func = move || {
let unixnano = $crate::get_unix_nano();
let include_unixnano = $crate::logger::INCLUDE_UNIXNANO.load(std::sync::atomic::Ordering::Relaxed);
let timezone = $crate::TIMEZONE.load(std::sync::atomic::Ordering::Relaxed);
let (date, time) = $crate::convert_unix_nano_to_date_and_time(unixnano, timezone);
let json_msg = match include_unixnano {
false => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic,
"message": format!($fmt, $($arg),*),
"data": "",
}),
true => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic,
"message": format!($fmt, $($arg),*),
"data": "",
"unixnano": unixnano,
}),
};
json_msg.to_string() + "\n"
};
$crate::LOG_SENDER.try_send($crate::LogMessage::LazyMessage($crate::LazyMessage::new(func))).expect("Failed to send log message");
}
}};
($level:expr, $topic:expr; $msg:expr $(,)?) => {{
if $level <= $crate::LogLevel::from_usize($crate::MAX_LOG_LEVEL.load(std::sync::atomic::Ordering::Relaxed)).expect("Invalid log level") {
let func = move || {
let unixnano = $crate::get_unix_nano();
let include_unixnano = $crate::logger::INCLUDE_UNIXNANO.load(std::sync::atomic::Ordering::Relaxed);
let timezone = $crate::TIMEZONE.load(std::sync::atomic::Ordering::Relaxed);
let (date, time) = $crate::convert_unix_nano_to_date_and_time(unixnano, timezone);
let json_msg = match include_unixnano {
false => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic.to_string(),
"message": $msg
}),
true => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": $topic.to_string(),
"message": $msg,
"unixnano": unixnano,
}),
};
json_msg.to_string() + "\n"
};
$crate::LOG_SENDER.try_send($crate::LogMessage::LazyMessage($crate::LazyMessage::new(func))).expect("Failed to send log message");
}
}};
($level:expr, $key:ident = $value:expr) => {{
if $level <= $crate::LogLevel::from_usize($crate::MAX_LOG_LEVEL.load(std::sync::atomic::Ordering::Relaxed)).expect("Invalid log level") {
let func = move || {
let unixnano = $crate::get_unix_nano();
let include_unixnano = $crate::logger::INCLUDE_UNIXNANO.load(std::sync::atomic::Ordering::Relaxed);
let json_obj = $crate::serde_json::json!({
$(
stringify!($key): $value,
)+
});
let timezone = $crate::TIMEZONE.load(std::sync::atomic::Ordering::Relaxed);
let (date, time) = $crate::convert_unix_nano_to_date_and_time(unixnano, timezone);
let json_msg = match include_unixnano {
false => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": "",
"data": json_obj,
"message": "",
}),
true => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"topic": "",
"data": json_obj,
"message": "",
"unixnano": unixnano,
}),
};
json_msg.to_string() + "\n"
};
$crate::LOG_SENDER.try_send($crate::LogMessage::LazyMessage($crate::LazyMessage::new(func))).expect("Failed to send log message");
}
}};
($level:expr, $($key:ident = $value:expr),+ $(,)?) => {{
if $level <= $crate::LogLevel::from_usize($crate::MAX_LOG_LEVEL.load(std::sync::atomic::Ordering::Relaxed)).expect("Invalid log level") {
let func = move || {
let unixnano = $crate::get_unix_nano();
let include_unixnano = $crate::logger::INCLUDE_UNIXNANO.load(std::sync::atomic::Ordering::Relaxed);
let json_obj = $crate::serde_json::json!({
$(
stringify!($key): $value,
)+
});
let timezone = $crate::TIMEZONE.load(std::sync::atomic::Ordering::Relaxed);
let (date, time) = $crate::convert_unix_nano_to_date_and_time(unixnano, timezone);
let json_msg = match include_unixnano {
false => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"data": json_obj,
"topic": "",
"message": "",
}),
true => $crate::serde_json::json!({
"date": date,
"time": time,
"offset": timezone,
"level": $level.to_string(),
"src": format!("{}:{}", file!(), line!()),
"data": json_obj,
"topic": "",
"message": "",
"unixnano": unixnano,
}),
};
json_msg.to_string() + "\n"
};
$crate::LOG_SENDER.try_send($crate::LogMessage::LazyMessage($crate::LazyMessage::new(func))).expect("Failed to send log message");
}
}};
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use serde::Serialize;
use crate::{Logger, LogLevel};
use crate::TimeZone;
#[derive(Debug, Clone, Serialize)]
pub enum Hello {
World,
FlashLog,
}
impl std::fmt::Display for Hello {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Hello::World => write!(f, "World"),
Hello::FlashLog => write!(f, "FlashLog"),
}
}
}
#[derive(Debug, Serialize, Clone)]
pub struct TestStruct {
pub test: i32,
}
#[derive(Debug, Serialize, Clone)]
pub struct TestStruct2 {
pub test: i32,
}
#[test]
fn test_logger() -> Result<()> {
let _guard = Logger::initialize()
.with_console_report(true)
.with_msg_buffer_size(1_000_000)
.with_msg_flush_interval(1_000_000_000)
.with_max_log_level(LogLevel::Trace)
.with_timezone(TimeZone::Local)
.include_unixnano(false)
.launch();
flash_error!(Hello::FlashLog);
flash_error!(Hello::World);
flash_error!("Hello");
flash_error!("Hello"; "FlashLog");
flash_error!("Hello"; "FlashLog"; version = "0.1.0");
flash_error!("Hello"; "FlashLog"; version = "0.1.0", author = "John Doe");
flash_error!(version = "0.1.0");
flash_error!(version = "0.1.0", author = "John Doe");
flash_error!("topic1"; "message {} {}", 1, 2);
flash_error!("topic2"; "message {} {}", 1, 2; struct_info = 1, struct_info2 = 2);
flash_error!("topic2"; "message {} {}", 1, 2; Hello = Hello::FlashLog);
let test_info = TestStruct { test: 1 };
let test_info2 = TestStruct2 { test: 2 };
flash_error!("topic2"; "message {} {}", 1, 2; TestStruct = test_info, TestStruct2 = test_info2);
flush!();
flash_warn!(Hello::World);
flash_warn!("Hello");
flash_warn!("Hello"; "FlashLog");
flash_warn!("Hello"; "FlashLog"; version = "0.1.0");
flash_warn!("Hello"; "FlashLog"; version = "0.1.0", author = "John Doe");
flash_warn!(version = "0.1.0");
flash_warn!(version = "0.1.0", author = "John Doe");
flash_warn!("topic1"; "message {} {}", 1, 2);
flash_warn!("topic2"; "message {} {}", 1, 2; struct_info = 1, struct_info2 = 2);
flash_warn!("topic2"; "message {} {}", 1, 2; Hello = Hello::FlashLog);
let test_info = TestStruct { test: 1 };
flash_warn!("topic2"; "message {} {}", 1, 2; TestStruct = test_info);
flush!();
flash_info!(Hello::World);
flash_info!(Hello::FlashLog);
flash_info!("Hello");
flash_info!("Hello"; "FlashLog");
flash_info!("Hello"; "FlashLog"; version = "0.1.0");
flash_info!("Hello"; "FlashLog"; version = "0.1.0", author = "John Doe");
flash_info!(version = "0.1.0");
flash_info!(version = "0.1.0", author = "John Doe");
flash_info!("topic1"; "message {} {}", 1, 2);
flash_info!("topic2"; "message {} {}", 1, 2; struct_info = 1, struct_info2 = 2);
flash_info!("topic2"; "message {} {}", 1, 2; Hello = Hello::FlashLog);
let test_info = TestStruct { test: 1 };
flash_info!("topic2"; "message {} {}", 1, 2; TestStruct = test_info);
flush!();
flash_debug!(Hello::World);
flash_debug!("Hello");
flash_debug!("Hello"; "FlashLog");
flash_debug!("Hello"; "FlashLog"; version = "0.1.0");
flash_debug!("Hello"; "FlashLog"; version = "0.1.0", author = "John Doe");
flash_debug!(version = "0.1.0");
flash_debug!(version = "0.1.0", author = "John Doe");
flash_debug!("topic1"; "message {} {}", 1, 2);
flash_debug!("topic2"; "message {} {}", 1, 2; struct_info = 1, struct_info2 = 2);
flash_debug!("topic2"; "message {} {}", 1, 2; Hello = Hello::FlashLog);
let test_info = TestStruct { test: 1 };
flash_debug!("topic2"; "message {} {}", 1, 2; TestStruct = test_info);
flush!();
flash_trace!(Hello::World);
flash_trace!("Hello");
flash_trace!("Hello"; "FlashLog");
flash_trace!("Hello"; "FlashLog"; version = "0.1.0");
flash_trace!("Hello"; "FlashLog"; version = "0.1.0", author = "John Doe");
flash_trace!(version = "0.1.0");
flash_trace!(version = "0.1.0", author = "John Doe");
flash_trace!("topic1"; "message {} {}", 1, 2);
flash_trace!("topic2"; "message {} {}", 1, 2; struct_info = 1, struct_info2 = 2);
flash_trace!("topic2"; "message {} {}", 1, 2; Hello = Hello::FlashLog);
let test_info = TestStruct { test: 1 };
flash_trace!("topic2"; "message {} {}", 1, 2; TestStruct = test_info);
crate::flush!();
assert!(true);
Ok(())
}
}