package l4g import ( "fmt" "os" "path/filepath" "time" ) type FileLogger struct { filePath string } func NewFileLogger(filePath string) *FileLogger { return &FileLogger{filePath: filePath} } func (f *FileLogger) Write(entry Entry) error { err := f.ensureLogFileExists() if err != nil { return err } file, err := os.OpenFile(f.filePath, os.O_APPEND|os.O_WRONLY, 0644) if err != nil { return fmt.Errorf("failed to open log file: %w", err) } defer file.Close() timestamp := entry.Timestamp.Format(time.RFC3339) var category string switch entry.Category { case CATEGORY_SYSTEM: category = "SYSTEM" case CATEGORY_ADMIN: category = "ADMIN" case CATEGORY_USER: category = "USER" case CATEGORY_ORG: category = "ORG" case CATEGORY_AUDIT: category = "AUDIT" case CATEGORY_AUTH: category = "AUTH" default: category = "UNKNOWN" } var logType string switch entry.LogType { case TYPE_DEBUG: logType = "DEBUG" case TYPE_INFO: logType = "INFO" case TYPE_WARN: logType = "WARN" case TYPE_ERROR: logType = "ERROR" default: logType = "UNKNOWN" } content := "" if entry.Content != nil { content = *entry.Content } logLine := fmt.Sprintf("[%s] %s/%s: %s", timestamp, category, logType, content) if entry.StructuredContent != nil { logLine += fmt.Sprintf(" | Details: %s", *entry.StructuredContent) } logLine += "\n" _, err = file.WriteString(logLine) if err != nil { return fmt.Errorf("failed to write to log file: %w", err) } return nil } func (f *FileLogger) Fatal(entry Entry) error { err := f.Write(entry) if err != nil { return err } os.Exit(1) return nil } func (f *FileLogger) ensureLogFileExists() error { dir := filepath.Dir(f.filePath) if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("failed to create log directory: %w", err) } if _, err := os.Stat(f.filePath); os.IsNotExist(err) { file, err := os.Create(f.filePath) if err != nil { return fmt.Errorf("failed to create log file: %w", err) } file.Close() } return nil }