extern crate env_logger;
pub fn initialize_logger() {
{
use std::sync::atomic::{AtomicBool, Ordering};
static LOGGER_INITIALIZED: AtomicBool = AtomicBool::new(false);
if LOGGER_INITIALIZED.swap(true, Ordering::SeqCst) {
return;
}
}
use std::io::IsTerminal;
use tracing_subscriber::prelude::*;
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::from_default_env())
.with(
tracing_tree::HierarchicalLayer::new(1)
.with_ansi(std::io::stderr().is_terminal())
.with_indent_lines(true)
.with_bracketed_fields(true)
.with_timer(tracing_tree::time::Uptime::default()),
)
.init();
}
#[macro_export]
macro_rules! code_location {
($color:ident) => {{
fn f() {}
fn type_name_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
let name = type_name_of(f);
let path: Vec<_> = name.split("::").collect();
let mut name = path.iter().rev().skip(1).next().unwrap().to_string();
let line = line!();
let file = file!();
let mut location = format!("{file}:{line}");
use std::io::IsTerminal;
if std::io::stderr().is_terminal() {
use colored::Colorize;
name = name.$color().to_string();
location = location.dimmed().to_string();
}
format!("in {name} at {location}")
}};
}
#[macro_export]
macro_rules! trace {
($($arg:tt)+) => {{
tracing::trace!("{}:\n{}", $crate::code_location!(yellow), format!($($arg)+))
}};
() => {{
tracing::trace!("{}", $crate::code_location!(yellow))
}};
}
#[macro_export]
macro_rules! error {
($($arg:tt)+) => {{
tracing::error!("{}:\n{}", $crate::code_location!(red), format!($($arg)+))
}};
}
#[macro_export]
macro_rules! warn {
($($arg:tt)+) => {{
tracing::warn!("{}:\n{}", $crate::code_location!(yellow), format!($($arg)+))
}};
}
#[macro_export]
macro_rules! info {
($($arg:tt)+) => {{
tracing::info!("{}: {}", $crate::code_location!(yellow), format!($($arg)+))
}};
() => {{
tracing::info!("{}", $crate::code_location!(yellow))
}};
}