package logger import ( "os" "path/filepath" "time" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) // Init initializes the logger with file and console output func Init(logDir, logLevel string) (*zap.Logger, error) { // Ensure log directory exists if err := os.MkdirAll(logDir, 0755); err != nil { return nil, err } // Parse log level var level zapcore.Level if err := level.UnmarshalText([]byte(logLevel)); err != nil { level = zapcore.InfoLevel } // Create log file path with date logFile := filepath.Join(logDir, "oai_server-"+time.Now().Format("2006-01-02")+".log") // File writer with rotation fileWriter := zapcore.AddSync(&lumberjack.Logger{ Filename: logFile, MaxSize: 100, // megabytes MaxBackups: 10, MaxAge: 30, // days Compress: true, }) // Console writer consoleWriter := zapcore.AddSync(os.Stdout) // Encoder config encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.TimeKey = "timestamp" encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // Create cores fileCore := zapcore.NewCore( zapcore.NewJSONEncoder(encoderConfig), fileWriter, level, ) consoleCore := zapcore.NewCore( zapcore.NewConsoleEncoder(encoderConfig), consoleWriter, level, ) // Combine cores core := zapcore.NewTee(fileCore, consoleCore) // Create logger logger := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel)) return logger, nil }