module main import time pub enum LogLevel { debug info warn error } pub struct Logger { level LogLevel json_mode bool } pub fn new_logger(level LogLevel, json_mode bool) Logger { return Logger{ level: level json_mode: json_mode } } fn level_string(level LogLevel) string { return match level { .debug { 'DEBUG' } .info { 'INFO' } .warn { 'WARN' } .error { 'ERROR' } } } fn level_icon(level LogLevel) string { return match level { .debug { '🔍' } .info { 'â„šī¸ ' } .warn { 'âš ī¸ ' } .error { '❌' } } } fn (l Logger) should_log(level LogLevel) bool { return int(level) >= int(l.level) } pub fn (l Logger) log(level LogLevel, source string, event string, message string) { if !l.should_log(level) { return } if l.json_mode { l.log_json(level, source, event, message) } else { l.log_human(level, source, event, message) } } fn (l Logger) log_json(level LogLevel, source string, event string, message string) { timestamp := time.now().format_rfc3339() level_str := level_string(level) // Manual JSON construction — simple enough to avoid importing json for each log line // Escape backslashes and quotes in message escaped := escape_json(message) output := '{"timestamp":"${timestamp}","level":"${level_str}","source":"${source}","event":"${event}","message":"${escaped}"}' if level == .error { eprintln(output) } else { println(output) } } fn escape_json(s string) string { mut result := s.clone() result = result.replace('\\', '\\\\') result = result.replace('"', '\\"') result = result.replace('\n', '\\n') result = result.replace('\r', '\\r') result = result.replace('\t', '\\t') return result } fn (l Logger) log_human(level LogLevel, source string, _event string, message string) { icon := level_icon(level) ts := time.now() ts_str := format_time_compact(ts) output := '${ts_str} ${icon} [${source}] ${message}' if level == .error { eprintln(output) } else if level == .warn { eprintln(output) } else { println(output) } } // format_time_compact returns "HH:MM:SS" (compact time for console output) fn format_time_compact(t time.Time) string { h := int(t.hour) m := int(t.minute) s := int(t.second) return '${h:02d}:${m:02d}:${s:02d}' } pub fn (l Logger) debug(source string, event string, message string) { l.log(.debug, source, event, message) } pub fn (l Logger) info(source string, event string, message string) { l.log(.info, source, event, message) } pub fn (l Logger) warn(source string, event string, message string) { l.log(.warn, source, event, message) } pub fn (l Logger) error(source string, event string, message string) { l.log(.error, source, event, message) }