natefinch / lumberjack

lumberjack is a log rolling package for Go
MIT License
4.8k stars 591 forks source link

Your rotate metod blocks logging at all while rotation, gzip files and other operations #55

Open ilya1st opened 6 years ago

ilya1st commented 6 years ago
func (l *Logger) Rotate() error {
    l.mu.Lock()
    defer l.mu.Unlock()
    return l.rotate()
}

So while you rename, gzip, reopen files logger Write blocks and wait while operation ends. This is not right way.

Right way is do that in the following order:

  1. rename files + mowe current file to xxx.log.1
  2. open new log file.
  3. l.mu.Lock(), assign new opened file, l.mu.Unlock
  4. do all other operations all you want.(gzip some of files, etc.)

In this case you make Write to wait while switch file to new. And you need add another mutex to logger to guarantee that Logger.Rotate() operations running only once a time.

natefinch commented 6 years ago

The compression and log cleanup is done in a different goroutine than logging. The main goroutine only blocks long enough to pass a boolean to the channel the compressor sits in. The only way this could block on the compression is if you manage to run past your max log size in the new file before the old file is finished compressing.

ilya1st commented 6 years ago

Yes, it may run in different gorotine but it uses same mutex as Logger.Write() use. That's why every gorotine which run Logger.Write() while rotate running will wait for Mutex.Unlock() call. So you can stop program execution during log rotation process. Here https://github.com/ilya1st/rotatewriter I've written implementation of rotation which lock/unlok Write() mutex only to replace new opened file. But without gzip and other things.

motaoyaoyao commented 5 years ago

Hello,I am learning to use lumberjack and zap. However I met a question.When log file's size is over 2M(as code shown),it makes error and can't write log now: 2019-01-26 14:13:11.7670684 +0800 AWST m=+0.500000001 write error: can't rename log file: rename ./test.log test-2019-01-26T14-13-11.767.log: The process cannot access the file because it is being used by another process. The code data is shown: `var Logger zap.Logger // logpath 日志文件路径 // loglevel 日志级别 func initLogger(logpath string, loglevel string) zap.Logger { hook := lumberjack.Logger{ Filename: logpath, // 日志文件路径 MaxSize: 2, // megabytes MaxAge: 7, // days MaxBackups: 30, // 最多保留300个备份 Compress: true, // 是否压缩 disabled by default LocalTime: true, }

w := zapcore.AddSync(&hook)
// 设置日志级别,debug可以打印出info,debug,warn;info级别可以打印warn,info;warn只能打印warn
// debug->info->warn->error
var level zapcore.Level
switch loglevel {
case "debug":
    level = zap.DebugLevel
case "info":
    level = zap.InfoLevel
case "error":
    level = zap.ErrorLevel
default:
    level = zap.InfoLevel
}
encoderConfig := zap.NewProductionEncoderConfig()
// 时间格式
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder

core := zapcore.NewCore(
    zapcore.NewConsoleEncoder(encoderConfig),
    w,
    level,
)

logger := zap.New(core)
logger.Info("DefaultLogger init success")
return logger

}

/日志模块的初始化/ func init() { // 历史记录日志名字为:all-2018-11-15T07-45-51.763.log,服务重新启动,日志会追加,不会删除 Logger = initLogger("./test.log", "debug") for i := 0; i < 24080; i++ { Logger.Info("[RTCAudioService][SDK-ROOM][RoomId:10010][Uuid:123456]",zap.String("msg", callDelSessionFromMap del room success)) Logger.Info(fmt.Sprint("[test log] ", i), zap.Int("line", 47)) //Logger.Info(fmt.Sprint("[Info log] ", i), zap.String("level", {"a":"4","b":"5"})) //Logger.Warn(fmt.Sprint("[Info log] ", i), zap.String("level", {"a":"7","b":"8"}))

}

}` Can you help me figure out the reason that the error occurs?

xiegeo commented 5 years ago

@motaoyaoyao Please file a new issue.