mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-29 12:16:16 +08:00
91150bb770
Signed-off-by: Tw <tw19881113@gmail.com>
125 lines
3.1 KiB
Go
125 lines
3.1 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"gopkg.in/natefinch/lumberjack.v2"
|
|
)
|
|
|
|
// LogRoller implements a type that provides a rolling logger.
|
|
type LogRoller struct {
|
|
Filename string
|
|
MaxSize int
|
|
MaxAge int
|
|
MaxBackups int
|
|
Compress bool
|
|
LocalTime bool
|
|
}
|
|
|
|
// 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 {
|
|
absPath, err := filepath.Abs(l.Filename)
|
|
if err != nil {
|
|
absPath = l.Filename // oh well, hopefully they're consistent in how they specify the filename
|
|
}
|
|
lj, has := lumberjacks[absPath]
|
|
if !has {
|
|
lj = &lumberjack.Logger{
|
|
Filename: l.Filename,
|
|
MaxSize: l.MaxSize,
|
|
MaxAge: l.MaxAge,
|
|
MaxBackups: l.MaxBackups,
|
|
Compress: l.Compress,
|
|
LocalTime: l.LocalTime,
|
|
}
|
|
lumberjacks[absPath] = lj
|
|
}
|
|
return lj
|
|
}
|
|
|
|
// IsLogRollerSubdirective is true if the subdirective is for the log roller.
|
|
func IsLogRollerSubdirective(subdir string) bool {
|
|
return subdir == directiveRotateSize ||
|
|
subdir == directiveRotateAge ||
|
|
subdir == directiveRotateKeep ||
|
|
subdir == directiveRotateCompress
|
|
}
|
|
|
|
var invalidRollerParameterErr = errors.New("invalid roller parameter")
|
|
|
|
// ParseRoller parses roller contents out of c.
|
|
func ParseRoller(l *LogRoller, what string, where ...string) error {
|
|
if l == nil {
|
|
l = DefaultLogRoller()
|
|
}
|
|
|
|
// rotate_compress doesn't accept any parameters.
|
|
// others only accept one parameter
|
|
if (what == directiveRotateCompress && len(where) != 0) ||
|
|
(what != directiveRotateCompress && len(where) != 1) {
|
|
return invalidRollerParameterErr
|
|
}
|
|
|
|
var (
|
|
value int
|
|
err error
|
|
)
|
|
if what != directiveRotateCompress {
|
|
value, err = strconv.Atoi(where[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
switch what {
|
|
case directiveRotateSize:
|
|
l.MaxSize = value
|
|
case directiveRotateAge:
|
|
l.MaxAge = value
|
|
case directiveRotateKeep:
|
|
l.MaxBackups = value
|
|
case directiveRotateCompress:
|
|
l.Compress = true
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DefaultLogRoller will roll logs by default.
|
|
func DefaultLogRoller() *LogRoller {
|
|
return &LogRoller{
|
|
MaxSize: defaultRotateSize,
|
|
MaxAge: defaultRotateAge,
|
|
MaxBackups: defaultRotateKeep,
|
|
Compress: false,
|
|
LocalTime: true,
|
|
}
|
|
}
|
|
|
|
const (
|
|
// defaultRotateSize is 100 MB.
|
|
defaultRotateSize = 100
|
|
// defaultRotateAge is 14 days.
|
|
defaultRotateAge = 14
|
|
// defaultRotateKeep is 10 files.
|
|
defaultRotateKeep = 10
|
|
|
|
directiveRotateSize = "rotate_size"
|
|
directiveRotateAge = "rotate_age"
|
|
directiveRotateKeep = "rotate_keep"
|
|
directiveRotateCompress = "rotate_compress"
|
|
)
|
|
|
|
// lumberjacks maps log filenames to the logger
|
|
// that is being used to keep them rolled/maintained.
|
|
var lumberjacks = make(map[string]*lumberjack.Logger)
|