color-log 10.2.3

A Rust logging library that supports both asynchronous and synchronous logging. It provides multiple log levels, such as error, info, and debug. Users can define custom log handling methods and configure log file paths. The library supports log rotation, automatically creating a new log file when the current file reaches the specified size limit. It allows flexible logging configurations, making it suitable for both high-performance asynchronous applications and traditional synchronous logging scenarios. The asynchronous mode utilizes Tokio's async channels for efficient log buffering, while the synchronous mode writes logs directly to the file system.
Documentation
use super::*;

/// Blanket implementation for any function matching FileLoggerFuncTrait signature.
///
/// This allows any compatible closure or function to be used as a log formatter.
impl<F, T> FileLoggerFuncTrait<T> for F
where
    F: Fn(T) -> String + Send + Sync,
    T: AsRef<str>,
{
}

/// Default implementation for FileLogger configuration.
impl Default for FileLogger {
    /// Creates default FileLogger configuration.
    ///
    /// # Returns
    ///
    /// - `Self` - Default FileLogger instance with default path and file size limit.
    #[inline(always)]
    fn default() -> Self {
        Self {
            path: DEFAULT_LOG_DIR.to_owned(),
            limit_file_size: DEFAULT_LOG_FILE_SIZE,
            trace_dir: TRACE_DIR.to_owned(),
            debug_dir: DEBUG_DIR.to_owned(),
            info_dir: INFO_DIR.to_owned(),
            warn_dir: WARN_DIR.to_owned(),
            error_dir: ERROR_DIR.to_owned(),
        }
    }
}

impl FileLogger {
    /// Creates new FileLogger configuration with specified parameters.
    ///
    /// # Arguments
    ///
    /// - `P` - The path for storing log files, which will be converted to string slice.
    /// - `usize` - The maximum file size limit in bytes.
    ///
    /// # Returns
    ///
    /// - `Self` - A new FileLogger instance with specified configuration.
    #[inline(always)]
    pub fn new<P: AsRef<str>>(path: P, limit_file_size: usize) -> Self {
        Self {
            path: path.as_ref().to_owned(),
            limit_file_size,
            trace_dir: TRACE_DIR.to_owned(),
            debug_dir: DEBUG_DIR.to_owned(),
            info_dir: INFO_DIR.to_owned(),
            warn_dir: WARN_DIR.to_owned(),
            error_dir: ERROR_DIR.to_owned(),
        }
    }

    /// Checks if logging is enabled.
    ///
    /// # Returns
    ///
    /// - `bool` - True if logging is enabled.
    #[inline(always)]
    pub fn is_enable(&self) -> bool {
        *self.get_limit_file_size() != DISABLE_LOG_FILE_SIZE
    }

    /// Checks if logging is disabled.
    ///
    /// # Returns
    ///
    /// - `bool` - True if logging is disabled.
    #[inline(always)]
    pub fn is_disable(&self) -> bool {
        !self.is_enable()
    }

    /// Writes log data synchronously to specified directory.
    ///
    /// # Arguments
    ///
    /// - `T` - The data to be logged, which will be converted to string slice.
    /// - `L` - The log formatting function.
    /// - `&str` - The subdirectory for log file.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self for method chaining.
    fn write_sync<T, L>(&self, data: T, func: L, dir: &str) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        if self.is_disable() {
            return self;
        }
        let out: String = func(data);
        let path: String = get_log_path(dir, self.get_path(), self.get_limit_file_size());
        let _: Result<(), Error> = append_to_file(&path, out.as_bytes());
        self
    }

    /// Writes log data asynchronously to specified directory.
    ///
    /// # Arguments
    ///
    /// - `T` - The data to be logged, which will be converted to string slice.
    /// - `L` - The log formatting function.
    /// - `&str` - The subdirectory for log file.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self for method chaining.
    async fn write_async<T, L>(&self, data: T, func: L, dir: &str) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        if self.is_disable() {
            return self;
        }
        let out: String = func(data);
        let path: String = get_log_path(dir, self.get_path(), self.get_limit_file_size());
        let _: Result<(), Error> = async_append_to_file(&path, out.as_bytes()).await;
        self
    }

    /// Logs trace message synchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Trace data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub fn trace<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_sync(data, func, self.get_trace_dir())
    }

    /// Logs trace message asynchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Trace data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub async fn async_trace<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_async(data, func, self.get_trace_dir()).await
    }

    /// Logs debug message synchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Debug data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub fn debug<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_sync(data, func, self.get_debug_dir())
    }

    /// Logs debug message asynchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Debug data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub async fn async_debug<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_async(data, func, self.get_debug_dir()).await
    }

    /// Logs info message synchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Info data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub fn info<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_sync(data, func, self.get_info_dir())
    }

    /// Logs info message asynchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Info data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub async fn async_info<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_async(data, func, self.get_info_dir()).await
    }

    /// Logs warn message synchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Warn data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub fn warn<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_sync(data, func, self.get_warn_dir())
    }

    /// Logs warn message asynchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Warn data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub async fn async_warn<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_async(data, func, self.get_warn_dir()).await
    }

    /// Logs error message synchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Error data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub fn error<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_sync(data, func, self.get_error_dir())
    }

    /// Logs error message asynchronously.
    ///
    /// # Arguments
    ///
    /// - `T` - Error data to be logged, which will be converted to string slice.
    /// - `L` - FileLogger formatting function.
    ///
    /// # Returns
    ///
    /// - `&Self` - Reference to self.
    pub async fn async_error<T, L>(&self, data: T, func: L) -> &Self
    where
        T: AsRef<str>,
        L: FileLoggerFuncTrait<T>,
    {
        self.write_async(data, func, self.get_error_dir()).await
    }
}