rwadurian/backend/mpc-system/pkg/logger/logger.go

189 lines
4.7 KiB
Go

package logger
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var (
Log *zap.Logger
Sugar *zap.SugaredLogger
)
// Config holds logger configuration
type Config struct {
Level string `mapstructure:"level"`
Encoding string `mapstructure:"encoding"`
OutputPath string `mapstructure:"output_path"`
}
// Init initializes the global logger
func Init(cfg *Config) error {
level := zapcore.InfoLevel
if cfg != nil && cfg.Level != "" {
if err := level.UnmarshalText([]byte(cfg.Level)); err != nil {
return err
}
// Debug output to verify level parsing
println("DEBUG: Parsed level:", level.String())
}
encoding := "json"
if cfg != nil && cfg.Encoding != "" {
encoding = cfg.Encoding
}
outputPath := "stdout"
if cfg != nil && cfg.OutputPath != "" {
outputPath = cfg.OutputPath
}
atomicLevel := zap.NewAtomicLevelAt(level)
println("DEBUG: Created AtomicLevel:", atomicLevel.String())
zapConfig := zap.Config{
Level: atomicLevel,
Development: true, // Changed to true to test if this affects debug logging
DisableCaller: false,
DisableStacktrace: false,
Sampling: nil,
Encoding: encoding,
EncoderConfig: zapcore.EncoderConfig{
MessageKey: "message",
LevelKey: "level",
TimeKey: "time",
NameKey: "logger",
CallerKey: "caller",
FunctionKey: zapcore.OmitKey,
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
},
OutputPaths: []string{outputPath},
ErrorOutputPaths: []string{"stderr"},
}
var err error
Log, err = zapConfig.Build()
if err != nil {
return err
}
println("DEBUG: After Build, AtomicLevel:", atomicLevel.String())
println("DEBUG: After Build, Log.Level():", Log.Level().String())
// TEST: Try to log a debug message immediately after Build()
Log.Debug("INTERNAL TEST: Debug log immediately after Build()")
Log.Info("INTERNAL TEST: Info log immediately after Build()")
Sugar = Log.Sugar()
// Replace global zap logger to ensure our config takes effect
zap.ReplaceGlobals(Log)
// Debug output to verify logger initialization
println("DEBUG: Logger initialized with level:", Log.Level().String())
return nil
}
// InitDevelopment initializes logger for development environment
func InitDevelopment() error {
var err error
Log, err = zap.NewDevelopment()
if err != nil {
return err
}
Sugar = Log.Sugar()
return nil
}
// InitProduction initializes logger for production environment
func InitProduction() error {
var err error
Log, err = zap.NewProduction()
if err != nil {
return err
}
Sugar = Log.Sugar()
return nil
}
// Sync flushes any buffered log entries
func Sync() error {
if Log != nil {
return Log.Sync()
}
return nil
}
// WithFields creates a new logger with additional fields
func WithFields(fields ...zap.Field) *zap.Logger {
return Log.With(fields...)
}
// Debug logs a debug message
func Debug(msg string, fields ...zap.Field) {
Log.Debug(msg, fields...)
}
// Info logs an info message
func Info(msg string, fields ...zap.Field) {
Log.Info(msg, fields...)
}
// Warn logs a warning message
func Warn(msg string, fields ...zap.Field) {
Log.Warn(msg, fields...)
}
// Error logs an error message
func Error(msg string, fields ...zap.Field) {
Log.Error(msg, fields...)
}
// Fatal logs a fatal message and exits
func Fatal(msg string, fields ...zap.Field) {
Log.Fatal(msg, fields...)
}
// Panic logs a panic message and panics
func Panic(msg string, fields ...zap.Field) {
Log.Panic(msg, fields...)
}
// Field creates a zap field
func Field(key string, value interface{}) zap.Field {
return zap.Any(key, value)
}
// String creates a string field
func String(key, value string) zap.Field {
return zap.String(key, value)
}
// Int creates an int field
func Int(key string, value int) zap.Field {
return zap.Int(key, value)
}
// Err creates an error field
func Err(err error) zap.Field {
return zap.Error(err)
}
// Removed init() function to prevent it from overriding logger config.
// The logger will be initialized when Init() is explicitly called with config.
// func init() {
// // Initialize with development logger by default
// // This will be overridden when Init() is called with proper config
// if os.Getenv("ENV") == "production" {
// _ = InitProduction()
// } else {
// _ = InitDevelopment()
// }
// }