186 lines
4.3 KiB
Go
186 lines
4.3 KiB
Go
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...)
|
|
}
|