loggur 0.1.0

로깅 크레이트
Documentation
use std::fs::{File, OpenOptions};
use std::io::{self, Write};
use std::path::Path;
use std::sync::Mutex;

use chrono::Local;
use lazy_static::lazy_static;

use crate::{FancyLogger, LogLevel};

// 파일 로거 상태를 저장하는 전역 변수
lazy_static! {
    static ref FILE_LOGGER: Mutex<Option<FileLogger>> = Mutex::new(None);
}

// 파일 로거 구현
pub struct FileLogger {
    file: File,
    level: LogLevel,
}

impl FileLogger {
    // 파일 로거 초기화
    pub fn init<P: AsRef<Path>>(path: P, level: LogLevel) -> io::Result<()> {
        let file = OpenOptions::new()
            .create(true)
            .append(true)
            .open(path)?;
        
        let mut file_logger = FILE_LOGGER.lock().unwrap();
        *file_logger = Some(FileLogger { file, level });
        
        Ok(())
    }
    
    // 로그 메시지를 파일에 기록
    pub fn log(level: LogLevel, message: &str, file: &str, line: u32) -> io::Result<()> {
        let mut file_logger = FILE_LOGGER.lock().unwrap();
        
        if let Some(logger) = file_logger.as_mut() {
            if level >= logger.level {
                let now = Local::now();
                let timestamp = now.format("%Y-%m-%d %H:%M:%S%.3f").to_string();
                
                writeln!(
                    logger.file,
                    "{} [{}] [{}:{}] {}",
                    timestamp,
                    level,
                    file,
                    line,
                    message
                )?;
            }
        }
        
        Ok(())
    }
}

// 로그 포맷터 구현
pub struct LogFormatter {
    format: String,
}

impl LogFormatter {
    pub fn new(format: &str) -> Self {
        Self {
            format: format.to_string(),
        }
    }
    
    pub fn format(&self, level: LogLevel, message: &str, file: &str, line: u32) -> String {
        let now = Local::now();
        let timestamp = now.format("%Y-%m-%d %H:%M:%S%.3f").to_string();
        
        let mut result = self.format.clone();
        result = result.replace("{timestamp}", &timestamp);
        result = result.replace("{level}", &level.to_string());
        result = result.replace("{message}", message);
        result = result.replace("{file}", file);
        result = result.replace("{line}", &line.to_string());
        
        result
    }
}

// FancyLogger 확장 기능
impl FancyLogger {
    // 파일 로깅 초기화
    pub fn init_file_logging<P: AsRef<Path>>(path: P, level: LogLevel) -> io::Result<()> {
        FileLogger::init(path, level)
    }
    
    // 파일에 로그 기록
    pub fn log_to_file(level: LogLevel, message: &str, file: &str, line: u32) -> io::Result<()> {
        FileLogger::log(level, message, file, line)
    }
    
    // 콘솔과 파일 모두에 로그 기록
    pub fn log_everywhere(level: LogLevel, message: &str, file: &str, line: u32) -> io::Result<()> {
        // 콘솔에 로그 기록
        Self::log(level, message, file, line);
        
        // 파일에 로그 기록
        FileLogger::log(level, message, file, line)
    }
}