package logger import ( "fmt" "io" "os" "path/filepath" "sync" "time" ) var ( instance *Logger once sync.Once ) // Logger handles application logging type Logger struct { file *os.File mu sync.Mutex path string } // Init initializes the logger with timestamp-based filename func Init() error { var err error once.Do(func() { // Create logs directory logsDir := "logs" if mkErr := os.MkdirAll(logsDir, 0755); mkErr != nil { err = mkErr return } // Create log file with timestamp timestamp := time.Now().Format("2006-01-02_15-04-05") filename := filepath.Join(logsDir, fmt.Sprintf("%s.log", timestamp)) f, openErr := os.Create(filename) if openErr != nil { err = openErr return } instance = &Logger{ file: f, path: filename, } Info("Logger initialized: %s", filename) }) return err } // Close closes the logger func Close() { if instance != nil && instance.file != nil { instance.file.Close() } } // GetPath returns the log file path func GetPath() string { if instance != nil { return instance.path } return "" } // log writes a log entry func log(level, format string, args ...interface{}) { if instance == nil { return } instance.mu.Lock() defer instance.mu.Unlock() timestamp := time.Now().Format("15:04:05.000") msg := fmt.Sprintf(format, args...) line := fmt.Sprintf("[%s] [%s] %s\n", timestamp, level, msg) instance.file.WriteString(line) instance.file.Sync() } // Debug logs a debug message func Debug(format string, args ...interface{}) { log("DEBUG", format, args...) } // Info logs an info message func Info(format string, args ...interface{}) { log("INFO", format, args...) } // Warn logs a warning message func Warn(format string, args ...interface{}) { log("WARN", format, args...) } // Error logs an error message func Error(format string, args ...interface{}) { log("ERROR", format, args...) } // Writer returns an io.Writer that logs to the file func Writer() io.Writer { if instance != nil { return instance.file } return os.Stdout }