package logger import ( "log" "os" "fmt" "path/filepath" "time" ) type Logger interface { Printf(format string, v ...any) Fatalf(format string, v ...any) } type stdLogger struct { l *log.Logger } func (s *stdLogger) Printf(format string, v ...any) { s.l.Printf(format, v...) } func (s *stdLogger) Fatalf(format string, v ...any) { s.l.Fatalf(format, v...) } var defaultLogger Logger = &stdLogger{ l: log.New(os.Stdout, "[app] ", log.LstdFlags|log.Lshortfile), } func L() Logger { return defaultLogger } func SetLogger(l Logger) { if l != nil { defaultLogger = l } } type prefLogger struct { prefix string } func (p *prefLogger) Printf(format string, v ...any) { defaultLogger.Printf("%s %s", p.prefix, fmt.Sprintf(format, v...)) } func (p *prefLogger) Fatalf(format string, v ...any) { defaultLogger.Fatalf("%s %s", p.prefix, fmt.Sprintf(format, v...)) } func WithPrefix(prefix string) Logger { return &prefLogger{prefix: prefix} } func SetupFile(path string) error { if path == "" { return fmt.Errorf("log file path empty") } if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return err } f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if err != nil { return err } defaultLogger = &stdLogger{ l: log.New(f, "[app] ", log.LstdFlags|log.Lshortfile), } return nil } func SetupTimezone(tz string) error { if tz == "" { return fmt.Errorf("timezone empty") } loc, err := time.LoadLocation(tz) if err != nil { return err } time.Local = loc return nil }