Skip to main content

rustbasic_core/
logger.rs

1/* ---------------------------------------------------------
2 * 📑 LABEL: LOGGER & BANNER (config/logger.rs)
3 * Pengaturan logging (Terminal + File) dan tampilan visual startup.
4 * --------------------------------------------------------- */
5
6use tracing_subscriber::{fmt, EnvFilter, prelude::*, registry};
7use tracing_appender::non_blocking::WorkerGuard;
8use tracing_subscriber::fmt::format::{FormatEvent, FormatFields};
9use tracing_subscriber::fmt::FmtContext;
10use tracing::{Event, Subscriber, Level};
11use std::fmt as std_fmt;
12use colored::*;
13
14struct CustomFormatter;
15
16impl<S, N> FormatEvent<S, N> for CustomFormatter
17where
18    S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
19    N: for<'a> FormatFields<'a> + 'static,
20{
21    fn format_event(
22        &self,
23        _ctx: &FmtContext<'_, S, N>,
24        mut writer: fmt::format::Writer<'_>,
25        event: &Event<'_>,
26    ) -> std_fmt::Result {
27        let metadata = event.metadata();
28        let level = metadata.level();
29        let timestamp = chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%.6fZ");
30
31        // Format: [LEVEL] TIMESTAMP MESSAGE
32        let level_str = format!("[{}]", level);
33        let level_colored = match *level {
34            Level::ERROR => level_str.red().bold(),
35            Level::WARN => level_str.yellow().bold(),
36            Level::INFO => level_str.green().bold(),
37            Level::DEBUG => level_str.blue().bold(),
38            Level::TRACE => level_str.magenta().bold(),
39        };
40
41        write!(writer, "{} {} ", level_colored, timestamp.to_string().dimmed())?;
42        
43        _ctx.format_fields(writer.by_ref(), event)?;
44        writeln!(writer)
45    }
46}
47
48pub fn init() -> WorkerGuard {
49    let file_appender = tracing_appender::rolling::daily("storage/logs", "rustbasic.log");
50    let (non_blocking_file, guard) = tracing_appender::non_blocking(file_appender);
51
52    let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| 
53        "rustbasic=debug,tower_http=debug,axum_session=warn,sqlx=warn".into()
54    );
55
56    registry()
57        .with(env_filter)
58        .with(fmt::layer().event_format(CustomFormatter).with_ansi(true))
59        .with(fmt::layer().with_target(false).with_ansi(false).with_writer(non_blocking_file))
60        .init();
61
62    print_banner();
63    guard
64}
65
66fn print_banner() {
67    println!(r#"
68    
69    ██████╗ ██╗   ██╗███████╗████████╗██████╗  █████╗ ███████╗██╗ ██████╗
70    ██╔══██╗██║   ██║██╔════╝╚══██╔══╝██╔══██╗██╔══██╗██╔════╝██║██╔════╝
71    ██████╔╝██║   ██║███████╗   ██║   ██████╔╝███████║███████╗██║██║     
72    ██╔══██╗██║   ██║╚════██║   ██║   ██╔══██╗██╔══██║╚════██║██║██║     
73    ██║  ██║╚██████╔╝███████║   ██║   ██████╔╝██║  ██║███████║██║╚██████╗
74    ╚═╝  ╚═╝ ╚═════╝ ╚══════╝   ╚═╝   ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝ ╚═════╝
75    "#);
76    println!("    >> RustBasic Full-stack Framework - Version 2026 <<\n");
77}