TUN-3768: Reuse file loggers

This change is focused on fixing rotating loggers in Windows
where it was failing due to Windows file semantics disallowing
the rotation while that file was still being open (because we
had multiple lumberjacks pointing to the same file).

This is fixed by ensuring the initialization happens only once.
This commit is contained in:
Nuno Diegues 2021-01-17 20:31:41 +00:00
parent de27361ffa
commit 8c9d725eeb
1 changed files with 44 additions and 21 deletions

View File

@ -6,6 +6,7 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"sync"
"github.com/mattn/go-colorable" "github.com/mattn/go-colorable"
"github.com/rs/zerolog" "github.com/rs/zerolog"
@ -143,23 +144,40 @@ func createConsoleLogger(config ConsoleConfig) io.Writer {
} }
} }
type fileInitializer struct {
once sync.Once
writer io.Writer
creationError error
}
var (
singleFileInit fileInitializer
rotatingFileInit fileInitializer
)
func createFileWriter(config FileConfig) (io.Writer, error) { func createFileWriter(config FileConfig) (io.Writer, error) {
var logFile io.Writer singleFileInit.once.Do(func() {
fullpath := config.Fullpath()
// Try to open the existing file var logFile io.Writer
logFile, err := os.OpenFile(fullpath, os.O_APPEND|os.O_WRONLY, filePermMode) fullpath := config.Fullpath()
if err != nil {
// If the existing file wasn't found, or couldn't be opened, just ignore // Try to open the existing file
// it and recreate a new one. logFile, err := os.OpenFile(fullpath, os.O_APPEND|os.O_WRONLY, filePermMode)
logFile, err = createDirFile(config)
// If creating a new logfile fails, then we have no choice but to error out.
if err != nil { if err != nil {
return nil, err // If the existing file wasn't found, or couldn't be opened, just ignore
// it and recreate a new one.
logFile, err = createDirFile(config)
// If creating a new logfile fails, then we have no choice but to error out.
if err != nil {
singleFileInit.creationError = err
return
}
} }
}
return logFile, nil singleFileInit.writer = logFile
})
return singleFileInit.writer, singleFileInit.creationError
} }
func createDirFile(config FileConfig) (io.Writer, error) { func createDirFile(config FileConfig) (io.Writer, error) {
@ -183,14 +201,19 @@ func createDirFile(config FileConfig) (io.Writer, error) {
} }
func createRollingLogger(config RollingConfig) (io.Writer, error) { func createRollingLogger(config RollingConfig) (io.Writer, error) {
if err := os.MkdirAll(config.Dirname, dirPermMode); err != nil { rotatingFileInit.once.Do(func() {
return nil, err if err := os.MkdirAll(config.Dirname, dirPermMode); err != nil {
} rotatingFileInit.creationError = err
return
}
return &lumberjack.Logger{ rotatingFileInit.writer = &lumberjack.Logger{
Filename: path.Join(config.Dirname, config.Filename), Filename: path.Join(config.Dirname, config.Filename),
MaxBackups: config.maxBackups, MaxBackups: config.maxBackups,
MaxSize: config.maxSize, MaxSize: config.maxSize,
MaxAge: config.maxAge, MaxAge: config.maxAge,
}, nil }
})
return rotatingFileInit.writer, rotatingFileInit.creationError
} }