hotpath 0.16.0

One profiler for CPU, time, memory, and async code - quickly find and debug performance bottlenecks.
Documentation
#[cfg(not(feature = "dev"))]
#[macro_export]
#[doc(hidden)]
macro_rules! __hotpath_noop_log {
    ($($tt:tt)*) => {{
        let _ = format_args!($($tt)*);
    }};
}

#[cfg(not(feature = "dev"))]
#[allow(unused_imports)]
pub use crate::__hotpath_noop_log as debug;
#[cfg(not(feature = "dev"))]
#[allow(unused_imports)]
pub use crate::__hotpath_noop_log as error;
#[cfg(not(feature = "dev"))]
#[allow(unused_imports)]
pub use crate::__hotpath_noop_log as info;
#[cfg(not(feature = "dev"))]
#[allow(unused_imports)]
pub use crate::__hotpath_noop_log as trace;
#[cfg(not(feature = "dev"))]
#[allow(unused_imports)]
pub use crate::__hotpath_noop_log as warn;

#[cfg(feature = "dev")]
pub static DEV_LOG_PATH: std::sync::LazyLock<std::path::PathBuf> = std::sync::LazyLock::new(|| {
    std::env::var("HOTPATH_DEV_LOG_PATH")
        .map(std::path::PathBuf::from)
        .unwrap_or_else(|_| std::path::PathBuf::from("log/development.log"))
});

#[cfg(feature = "dev")]
static WRITER: std::sync::OnceLock<Option<std::sync::Mutex<std::io::BufWriter<std::fs::File>>>> =
    std::sync::OnceLock::new();

#[cfg(feature = "dev")]
#[allow(dead_code)]
pub fn init_logging() {
    let _ = WRITER.get_or_init(|| {
        if let Some(parent) = DEV_LOG_PATH.parent() {
            if !parent.as_os_str().is_empty() {
                std::fs::create_dir_all(parent).ok()?;
            }
        }
        let file = std::fs::OpenOptions::new()
            .create(true)
            .append(true)
            .open(&*DEV_LOG_PATH)
            .ok()?;
        Some(std::sync::Mutex::new(std::io::BufWriter::new(file)))
    });
}

#[cfg(feature = "dev")]
#[doc(hidden)]
pub fn __write_log(level: &'static str, args: std::fmt::Arguments<'_>) {
    use std::io::Write;
    let writer = match WRITER.get() {
        Some(Some(w)) => w,
        _ => return,
    };
    let Ok(mut guard) = writer.lock() else {
        return;
    };
    let now = current_timestamp();
    let _ = writeln!(*guard, "{} {} {}", now, level, args);
    let _ = guard.flush();
}

#[cfg(feature = "dev")]
fn current_timestamp() -> String {
    let offset = time::UtcOffset::current_local_offset().unwrap_or(time::UtcOffset::UTC);
    let now = time::OffsetDateTime::now_utc().to_offset(offset);
    let fmt = time::macros::format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]");
    now.format(&fmt).unwrap_or_default()
}

#[cfg(feature = "dev")]
#[macro_export]
#[doc(hidden)]
macro_rules! __hotpath_dev_log_trace {
    ($($tt:tt)*) => {{ $crate::dev_logging::__write_log("TRACE", std::format_args!($($tt)*)) }};
}
#[cfg(feature = "dev")]
#[macro_export]
#[doc(hidden)]
macro_rules! __hotpath_dev_log_debug {
    ($($tt:tt)*) => {{ $crate::dev_logging::__write_log("DEBUG", std::format_args!($($tt)*)) }};
}
#[cfg(feature = "dev")]
#[macro_export]
#[doc(hidden)]
macro_rules! __hotpath_dev_log_info {
    ($($tt:tt)*) => {{ $crate::dev_logging::__write_log("INFO", std::format_args!($($tt)*)) }};
}
#[cfg(feature = "dev")]
#[macro_export]
#[doc(hidden)]
macro_rules! __hotpath_dev_log_warn {
    ($($tt:tt)*) => {{ $crate::dev_logging::__write_log("WARN", std::format_args!($($tt)*)) }};
}
#[cfg(feature = "dev")]
#[macro_export]
#[doc(hidden)]
macro_rules! __hotpath_dev_log_error {
    ($($tt:tt)*) => {{ $crate::dev_logging::__write_log("ERROR", std::format_args!($($tt)*)) }};
}

#[cfg(feature = "dev")]
#[allow(unused_imports)]
pub use crate::__hotpath_dev_log_debug as debug;
#[cfg(feature = "dev")]
#[allow(unused_imports)]
pub use crate::__hotpath_dev_log_error as error;
#[cfg(feature = "dev")]
#[allow(unused_imports)]
pub use crate::__hotpath_dev_log_info as info;
#[cfg(feature = "dev")]
#[allow(unused_imports)]
pub use crate::__hotpath_dev_log_trace as trace;
#[cfg(feature = "dev")]
#[allow(unused_imports)]
pub use crate::__hotpath_dev_log_warn as warn;

#[cfg(not(feature = "dev"))]
#[allow(dead_code)]
pub fn init_logging() {}