package output import ( "fmt" "os" "github.com/fatih/color" "go.uber.org/zap" ) var ( // Global state for output formatting colorEnabled = true verboseMode = false // Colors colorInfo = color.New(color.FgBlue) colorSuccess = color.New(color.FgGreen) colorWarning = color.New(color.FgYellow) colorError = color.New(color.FgRed) colorHeader = color.New(color.FgBlue, color.Bold) ) // Logger provides structured logging with colored output type Logger struct { zap *zap.Logger } // NewLogger creates a new logger instance func NewLogger() *Logger { config := zap.NewDevelopmentConfig() config.DisableStacktrace = true config.Level = zap.NewAtomicLevelAt(zap.InfoLevel) if verboseMode { config.Level = zap.NewAtomicLevelAt(zap.DebugLevel) } logger, _ := config.Build() return &Logger{ zap: logger, } } // Sync flushes any buffered log entries func (l *Logger) Sync() error { return l.zap.Sync() } // Info logs an info message func (l *Logger) Info(msg string, keysAndValues ...interface{}) { l.zap.Sugar().Infow(msg, keysAndValues...) // Also print to stdout with formatting if colorEnabled { _, _ = fmt.Fprintf(os.Stdout, "%s %s\n", colorInfo.Sprint("INFO:"), msg) } else { _, _ = fmt.Fprintf(os.Stdout, "INFO: %s\n", msg) } } // Success logs a success message func (l *Logger) Success(msg string, keysAndValues ...interface{}) { l.zap.Sugar().Infow(msg, keysAndValues...) if colorEnabled { _, _ = fmt.Fprintf(os.Stdout, "%s %s\n", colorSuccess.Sprint("SUCCESS:"), msg) } else { _, _ = fmt.Fprintf(os.Stdout, "SUCCESS: %s\n", msg) } } // Warning logs a warning message func (l *Logger) Warning(msg string, keysAndValues ...interface{}) { l.zap.Sugar().Warnw(msg, keysAndValues...) if colorEnabled { fmt.Fprintf(os.Stderr, "%s %s\n", colorWarning.Sprint("WARNING:"), msg) } else { fmt.Fprintf(os.Stderr, "WARNING: %s\n", msg) } } // Error logs an error message func (l *Logger) Error(msg string, keysAndValues ...interface{}) { l.zap.Sugar().Errorw(msg, keysAndValues...) if colorEnabled { fmt.Fprintf(os.Stderr, "%s %s\n", colorError.Sprint("ERROR:"), msg) } else { fmt.Fprintf(os.Stderr, "ERROR: %s\n", msg) } } // Debug logs a debug message (only shown in verbose mode) func (l *Logger) Debug(msg string, keysAndValues ...interface{}) { l.zap.Sugar().Debugw(msg, keysAndValues...) if verboseMode { if colorEnabled { _, _ = fmt.Fprintf(os.Stdout, "%s %s\n", color.New(color.FgMagenta).Sprint("DEBUG:"), msg) } else { _, _ = fmt.Fprintf(os.Stdout, "DEBUG: %s\n", msg) } } } // Header prints a formatted header func (l *Logger) Header(msg string) { if colorEnabled { _, _ = fmt.Fprintf(os.Stdout, "\n%s\n\n", colorHeader.Sprintf("=== %s ===", msg)) } else { _, _ = fmt.Fprintf(os.Stdout, "\n=== %s ===\n\n", msg) } } // Printf provides formatted output func (l *Logger) Printf(format string, args ...interface{}) { fmt.Printf(format, args...) } // Print provides simple output func (l *Logger) Print(msg string) { fmt.Println(msg) } // Global functions for package-level access // DisableColor disables colored output func DisableColor() { colorEnabled = false color.NoColor = true } // SetVerbose enables or disables verbose mode func SetVerbose(enabled bool) { verboseMode = enabled } // Package-level convenience functions func Info(msg string) { if colorEnabled { _, _ = fmt.Fprintf(os.Stdout, "%s %s\n", colorInfo.Sprint("INFO:"), msg) } else { _, _ = fmt.Fprintf(os.Stdout, "INFO: %s\n", msg) } } func Success(msg string) { if colorEnabled { _, _ = fmt.Fprintf(os.Stdout, "%s %s\n", colorSuccess.Sprint("SUCCESS:"), msg) } else { _, _ = fmt.Fprintf(os.Stdout, "SUCCESS: %s\n", msg) } } func Warning(msg string) { if colorEnabled { fmt.Fprintf(os.Stderr, "%s %s\n", colorWarning.Sprint("WARNING:"), msg) } else { fmt.Fprintf(os.Stderr, "WARNING: %s\n", msg) } } func Error(msg string) { if colorEnabled { fmt.Fprintf(os.Stderr, "%s %s\n", colorError.Sprint("ERROR:"), msg) } else { fmt.Fprintf(os.Stderr, "ERROR: %s\n", msg) } } func Header(msg string) { if colorEnabled { _, _ = fmt.Fprintf(os.Stdout, "\n%s\n\n", colorHeader.Sprintf("=== %s ===", msg)) } else { _, _ = fmt.Fprintf(os.Stdout, "\n=== %s ===\n\n", msg) } } // Printf provides formatted output (package-level function) func Printf(format string, args ...interface{}) { fmt.Printf(format, args...) }