package logger import ( "encoding/json" "fmt" "os" "strings" "time" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) type CustomLogger struct { consoleLogger zerolog.Logger } type Message struct { Channel string `json:"channel"` Data map[string]interface{} `json:"data"` Meta map[string]interface{} `json:"meta,omitempty"` } // New creates a configured CustomLogger. func New() *CustomLogger { // Colorized console output consoleWriter := zerolog.ConsoleWriter{ Out: os.Stderr, TimeFormat: "2006-01-02 15:04:05", } return &CustomLogger{ consoleLogger: zerolog.New(consoleWriter). With(). Timestamp(). Logger(), } } func PrettyFormat(level, message string, metadata map[string]interface{}) string { timestamp := time.Now().Format("2006-01-02 15:04:05") base := fmt.Sprintf("[%s] %s| Message: %s", strings.ToUpper(level), timestamp, message) if len(metadata) > 0 { metaJSON, _ := json.Marshal(metadata) return fmt.Sprintf("%s | Metadata: %s", base, string(metaJSON)) } return base } func (l *CustomLogger) logToPostgres(level, message, service string, metadata map[string]interface{}) { err := CreateLog(level, message, service, metadata) if err != nil { // Fallback to console if DB fails log.Error().Err(err).Msg("Failed to write log to PostgreSQL") } } // --- Level-Specific Methods --- func (l *CustomLogger) Info(message, service string, fields map[string]interface{}) { l.consoleLogger.Info().Fields(fields).Msg(message) l.logToPostgres("info", message, service, fields) //PostLog(PrettyFormat("info", message, fields)) // Broadcast pretty message } func (l *CustomLogger) Warn(message, service string, fields map[string]interface{}) { l.consoleLogger.Error().Fields(fields).Msg(message) l.logToPostgres("warn", message, service, fields) //PostLog(PrettyFormat("warn", message, fields)) // Broadcast pretty message // Custom logic for errors (e.g., alerting) if len(fields) > 0 { l.consoleLogger.Warn().Msg("Additional error context captured") } } func (l *CustomLogger) Error(message, service string, fields map[string]interface{}) { l.consoleLogger.Error().Fields(fields).Msg(message) l.logToPostgres("error", message, service, fields) //PostLog(PrettyFormat("error", message, fields)) // Broadcast pretty message // Custom logic for errors (e.g., alerting) if len(fields) > 0 { l.consoleLogger.Warn().Msg("Additional error context captured") } } func (l *CustomLogger) Panic(message, service string, fields map[string]interface{}) { // Log to console (colored, with fields) l.consoleLogger.Error(). Str("service", service). Fields(fields). Msg(message + " (PANIC)") // Explicitly mark as panic // Log to PostgreSQL (sync to ensure it's saved before crashing) err := CreateLog("panic", message, service, fields) // isCritical=true if err != nil { l.consoleLogger.Error().Err(err).Msg("Failed to save panic log to PostgreSQL") } // Additional context (optional) if len(fields) > 0 { l.consoleLogger.Warn().Msg("Additional panic context captured") } CreateDiscordMsg(message) panic(message) } func (l *CustomLogger) Debug(message, service string, fields map[string]interface{}) { l.consoleLogger.Debug().Fields(fields).Msg(message) l.logToPostgres("debug", message, service, fields) }