use fstdout_logger::LoggerConfig;
use log::{LevelFilter, debug, error, info, warn};
use std::fmt::Write;
use std::thread::sleep;
use std::time::Duration;
fn main() {
println!("=== PRODUCTION LOGGER SIMULATION ===");
let prod_config = LoggerConfig::production();
println!("Production settings:");
println!(" - Log level: Info (no Debug or Trace messages)");
println!(" - File info: Hidden (cleaner logs)");
println!(" - Colors: Enabled (for better readability)");
println!(" - Date in console: Hidden (time only for brevity)\n");
format_and_print_logs("Production", &prod_config);
println!("\n\n=== DEVELOPMENT LOGGER SIMULATION ===");
let dev_config = LoggerConfig::development();
println!("Development settings:");
println!(" - Log level: Debug (includes debug messages)");
println!(" - File info: Shown (helps with debugging)");
println!(" - Colors: Enabled (for better readability)");
println!(" - Date in console: Hidden (time only for brevity)\n");
format_and_print_logs("Development", &dev_config);
println!("\nNote: In production mode, logs are more concise (no file info, only time)");
println!(
"but the log file still contains complete information including date and file details."
);
println!("\n=== ACTUAL LOGGER IMPLEMENTATION ===");
println!("Initializing a real logger with production settings...");
if let Err(e) = fstdout_logger::init_production_logger(Some("prod.log")) {
eprintln!("Failed to initialize logger: {e}");
return;
}
info!("This message was logged with the actual logger");
debug!("Debug info won't appear in production mode");
warn!("Warnings will appear");
error!("Errors will appear too");
println!("\nCheck 'prod.log' to see the file output format with full details!");
}
fn format_and_print_logs(context: &str, config: &LoggerConfig) {
let now = chrono::Local::now();
let timestamp = if config.show_date_in_stdout {
now.format("%Y-%m-%d %H:%M:%S").to_string()
} else {
now.format("%H:%M:%S").to_string()
};
let format_log = |level: &str, colored: bool, file_info: bool, msg: &str| {
let mut output = String::new();
let level_str = match (colored, level) {
(true, "ERROR") => "\x1b[1;31mERROR\x1b[0m", (true, "WARN") => "\x1b[1;33mWARN\x1b[0m", (true, "INFO") => "\x1b[1;34mINFO\x1b[0m", (true, "DEBUG") => "\x1b[32mDEBUG\x1b[0m", (true, "TRACE") => "TRACE", (_, _) => level, };
let time_part = if colored {
format!("\x1b[90m{timestamp}\x1b[0m") } else {
timestamp.clone()
};
if file_info {
let file_str = if colored {
"\x1b[90mexamples/production.rs:42\x1b[0m" } else {
"examples/production.rs:42"
};
write!(output, "[{time_part} {level_str} {file_str}] {msg}").unwrap();
} else {
write!(output, "[{time_part} {level_str}] {msg}").unwrap();
}
output
};
let msg = format!("{context} process starting up");
println!(
"{}",
format_log("INFO", config.use_colors, config.show_file_info, &msg)
);
let debug_msg = "Initializing subsystems with memory pool of 1024 bytes";
if config.level <= LevelFilter::Debug {
println!(
"{}",
format_log("DEBUG", config.use_colors, config.show_file_info, debug_msg)
);
}
for i in 1..=3 {
let msg = format!("Processing batch #{i}");
println!(
"{}",
format_log("INFO", config.use_colors, config.show_file_info, &msg)
);
if i == 2 {
let warn_msg = "Resource usage above threshold (82%)";
println!(
"{}",
format_log("WARN", config.use_colors, config.show_file_info, warn_msg)
);
}
sleep(Duration::from_millis(100)); }
let error_msg = "Failed to connect to database: timeout after 5 seconds";
println!(
"{}",
format_log("ERROR", config.use_colors, config.show_file_info, error_msg)
);
let end_msg = format!("{context} process completed");
println!(
"{}",
format_log("INFO", config.use_colors, config.show_file_info, &end_msg)
);
}