Commit 04da9c73 authored by Matthew Holt's avatar Matthew Holt

Create only one log roller per file across whole process (fixes #1363)

parent 16250da3
...@@ -2,6 +2,7 @@ package httpserver ...@@ -2,6 +2,7 @@ package httpserver
import ( import (
"io" "io"
"path/filepath"
"strconv" "strconv"
"github.com/mholt/caddy" "github.com/mholt/caddy"
...@@ -19,14 +20,30 @@ type LogRoller struct { ...@@ -19,14 +20,30 @@ type LogRoller struct {
} }
// GetLogWriter returns an io.Writer that writes to a rolling logger. // GetLogWriter returns an io.Writer that writes to a rolling logger.
// This should be called only from the main goroutine (like during
// server setup) because this method is not thread-safe; it is careful
// to create only one log writer per log file, even if the log file
// is shared by different sites or middlewares. This ensures that
// rolling is synchronized, since a process (or multiple processes)
// should not create more than one roller on the same file at the
// same time. See issue #1363.
func (l LogRoller) GetLogWriter() io.Writer { func (l LogRoller) GetLogWriter() io.Writer {
return &lumberjack.Logger{ absPath, err := filepath.Abs(l.Filename)
Filename: l.Filename, if err != nil {
MaxSize: l.MaxSize, absPath = l.Filename // oh well, hopefully they're consistent in how they specify the filename
MaxAge: l.MaxAge,
MaxBackups: l.MaxBackups,
LocalTime: l.LocalTime,
} }
lj, has := lumberjacks[absPath]
if !has {
lj = &lumberjack.Logger{
Filename: l.Filename,
MaxSize: l.MaxSize,
MaxAge: l.MaxAge,
MaxBackups: l.MaxBackups,
LocalTime: l.LocalTime,
}
lumberjacks[absPath] = lj
}
return lj
} }
// ParseRoller parses roller contents out of c. // ParseRoller parses roller contents out of c.
...@@ -62,3 +79,7 @@ func ParseRoller(c *caddy.Controller) (*LogRoller, error) { ...@@ -62,3 +79,7 @@ func ParseRoller(c *caddy.Controller) (*LogRoller, error) {
LocalTime: true, LocalTime: true,
}, nil }, nil
} }
// lumberjacks maps log filenames to the logger
// that is being used to keep them rolled/maintained.
var lumberjacks = make(map[string]*lumberjack.Logger)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment