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() // } // }