package logger import ( "encoding/json" "fmt" "os" "path/filepath" "time" "videnc-vibe/pkg/types" ) type Logger struct { infoPath string errorPath string structPath string infoFile *os.File errorFile *os.File structFile *os.File } func New(logDir string) (*Logger, error) { if err := os.MkdirAll(logDir, 0755); err != nil { return nil, fmt.Errorf("creating log directory: %w", err) } now := time.Now().Format("2006-01-02") infoPath := filepath.Join(logDir, fmt.Sprintf("info_%s.log", now)) errorPath := filepath.Join(logDir, fmt.Sprintf("error_%s.log", now)) structPath := filepath.Join(logDir, "structured.json") infoFile, err := os.OpenFile(infoPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return nil, fmt.Errorf("opening info log: %w", err) } errorFile, err := os.OpenFile(errorPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return nil, fmt.Errorf("opening error log: %w", err) } structFile, err := os.OpenFile(structPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return nil, fmt.Errorf("opening structured log: %w", err) } return &Logger{ infoPath: infoPath, errorPath: errorPath, structPath: structPath, infoFile: infoFile, errorFile: errorFile, structFile: structFile, }, nil } func (l *Logger) Info(message string) { timestamp := time.Now().Format("2006-01-02 15:04:05") entry := fmt.Sprintf("[%s] INFO: %s\n", timestamp, message) l.infoFile.WriteString(entry) l.writeStructured("info", message, "", "") } func (l *Logger) Error(message, err string) { timestamp := time.Now().Format("2006-01-02 15:04:05") entry := fmt.Sprintf("[%s] ERROR: %s - %s\n", timestamp, message, err) l.errorFile.WriteString(entry) l.writeStructured("error", message, err, "") } func (l *Logger) ErrorFile(file string, message, err string) { timestamp := time.Now().Format("2006-01-02 15:04:05") entry := fmt.Sprintf("[%s] ERROR: %s - %s (file: %s)\n", timestamp, message, err, file) l.errorFile.WriteString(entry) l.writeStructured("error", message, err, file) } func (l *Logger) writeStructured(level, message, err, file string) { entry := types.LogEntry{ Timestamp: time.Now(), Level: level, Message: message, Error: err, File: file, } data, _ := json.Marshal(entry) l.structFile.WriteString(string(data) + "\n") } func (l *Logger) Close() { l.infoFile.Close() l.errorFile.Close() l.structFile.Close() }