nightshade 0.14.2

A cross-platform data-oriented game engine.
Documentation
//! File-based logging configuration types.
//!
//! Stored on the `Window` resource so apps customize logging through
//! `world.resources.window.log_config` before launch.

/// Controls how log files are rotated.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogRotation {
    /// New log file each application launch (timestamp in filename).
    PerSession,
    /// One log file per day.
    Daily,
    /// Single log file, appended to on each launch.
    Never,
}

/// Configuration for file-based logging (desktop only, requires `tracing` feature).
#[derive(Debug, Clone)]
pub struct LogConfig {
    /// Directory for log files (relative to working directory).
    pub directory: String,
    /// Log rotation strategy.
    pub rotation: LogRotation,
    /// Default `RUST_LOG` filter when the environment variable is not set.
    pub default_filter: String,
    /// chrono format string for per-session log timestamps.
    /// Default: `"%Y-%m-%d_%H-%M-%S"` produces `2026-03-04_14-30-00`.
    pub timestamp_format: String,
}

impl Default for LogConfig {
    fn default() -> Self {
        Self {
            directory: "logs".to_string(),
            rotation: LogRotation::PerSession,
            default_filter: "info".to_string(),
            timestamp_format: "%Y-%m-%d_%H-%M-%S".to_string(),
        }
    }
}

#[cfg(all(not(target_arch = "wasm32"), feature = "tracing"))]
pub fn log_file_name(title: &str, config: &LogConfig) -> String {
    let sanitized: String = title
        .chars()
        .map(|character| {
            if character.is_alphanumeric() || character == '-' || character == '_' {
                character
            } else {
                '_'
            }
        })
        .collect();
    let base_name = if sanitized.is_empty() {
        "app".to_string()
    } else {
        sanitized.to_lowercase()
    };
    match config.rotation {
        LogRotation::PerSession => {
            let timestamp = chrono::Local::now().format(&config.timestamp_format);
            format!("{base_name}_{timestamp}.log")
        }
        LogRotation::Daily | LogRotation::Never => format!("{base_name}.log"),
    }
}