Documentation
¶
Overview ¶
Package timberjack provides a rolling logger with size-based and time-based rotation.
Timberjack is a simple, pluggable component for log rotation. It can rotate the active log file when any of the following occur:
- the file grows beyond MaxSize (size-based)
- the configured RotationInterval elapses (interval-based)
- a scheduled time is reached via RotateAt or RotateAtMinutes (clock-based)
- rotation is triggered explicitly via Rotate() (manual)
Rotated files can optionally be compressed with gzip or zstd. Cleanup is handled automatically. Old log files are removed based on MaxBackups and MaxAge.
Import:
import "github.com/DeRuina/timberjack"
Timberjack works with any logger that writes to an io.Writer, including the standard library’s log package.
Concurrency note: timberjack assumes a single process writes to the target files. Reusing the same Logger configuration across multiple processes on the same machine may lead to improper behavior.
Source code: https://github.com/DeRuina/timberjack
Example ¶
To use timberjack with the standard library's log package, just pass it into the SetOutput function when your application starts.
log.SetOutput(&Logger{
Filename: "/var/log/myapp/foo.log",
MaxSize: 500, // megabytes
MaxBackups: 3, // number of backups
MaxAge: 28, // days
Compress: true, // disabled by default
LocalTime: true, // use the local timezone
RotationInterval: time.Hour * 24, // rotate daily
})
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // empty BackupTimeFormatField ErrEmptyBackupTimeFormatField = errors.New("empty backupformat field") )
Functions ¶
This section is empty.
Types ¶
type Logger ¶
type Logger struct {
// Filename is the file to write logs to. Backup log files will be retained
// in the same directory. It uses <processname>-timberjack.log in
// os.TempDir() if empty.
Filename string `json:"filename" yaml:"filename"`
// MaxSize is the maximum size in megabytes of the log file before it gets
// rotated. It defaults to 100 megabytes.
MaxSize int `json:"maxsize" yaml:"maxsize"`
// MaxAge is the maximum number of days to retain old log files based on the
// timestamp encoded in their filename. Note that a day is defined as 24
// hours and may not exactly correspond to calendar days due to daylight
// savings, leap seconds, etc. The default is not to remove old log files
// based on age.
MaxAge int `json:"maxage" yaml:"maxage"`
// MaxBackups is the maximum number of old log files to retain. The default
// is to retain all old log files (though MaxAge may still cause them to get
// deleted.) MaxBackups counts distinct rotation events (timestamps).
MaxBackups int `json:"maxbackups" yaml:"maxbackups"`
// LocalTime determines if the time used for formatting the timestamps in
// backup files is the computer's local time. The default is to use UTC
// time.
LocalTime bool `json:"localtime" yaml:"localtime"`
// Deprecated: use Compression instead ("none" | "gzip" | "zstd").
Compress bool `json:"compress,omitempty" yaml:"compress,omitempty"`
// Compression selects the algorithm. If empty, legacy Compress is used.
// Allowed values: "none", "gzip", "zstd". Unknown => "none" (with a warning).
Compression string `json:"compression,omitempty" yaml:"compression,omitempty"`
// RotationInterval is the maximum duration between log rotations.
// If the elapsed time since the last rotation exceeds this interval,
// the log file is rotated, even if the file size has not reached MaxSize.
// The minimum recommended value is 1 minute. If set to 0, time-based rotation is disabled.
//
// Example: RotationInterval = time.Hour * 24 will rotate logs daily.
RotationInterval time.Duration `json:"rotationinterval" yaml:"rotationinterval"`
// BackupTimeFormat defines the layout for the timestamp appended to rotated file names.
// While other formats are allowed, it is recommended to follow the standard Go time layout
// (https://pkg.go.dev/time#pkg-constants). Use the ValidateBackupTimeFormat() method to check
// if the value is valid. It is recommended to call this method before using the Logger instance.
//
// WARNING: This field is assumed to be constant after initialization.
// WARNING: If invalid value is supplied then default format `2006-01-02T15-04-05.000` will be used.
//
// Example:
// BackupTimeFormat = `2006-01-02-15-04-05`
// will generate rotated backup files in the format:
// <logfilename>-2006-01-02-15-04-05-<rotationCriterion>-timberjack.log
// where `rotationCriterion` could be `time` or `size`.
BackupTimeFormat string `json:"backuptimeformat" yaml:"backuptimeformat"`
// RotateAtMinutes defines specific minutes within an hour (0-59) to trigger a rotation.
// For example, []int{0} for top of the hour, []int{0, 30} for top and half-past the hour.
// Rotations are aligned to the clock minute (second 0).
// This operates in addition to RotationInterval and MaxSize.
// If multiple rotation conditions are met, the first one encountered typically triggers.
RotateAtMinutes []int `json:"rotateAtMinutes" yaml:"rotateAtMinutes"`
// RotateAt defines specific time within a day to trigger a rotation.
// For example, []string{'00:00'} for midnight, []string{'00:00', '12:00'} for
// midnight and midday.
// Rotations are aligned to the clock minute (second 0).
// This operates in addition to RotationInterval and MaxSize.
// If multiple rotation conditions are met, the first one encountered typically triggers.
RotateAt []string `json:"rotateAt" yaml:"rotateAt"`
// AppendTimeAfterExt controls where the timestamp/reason go.
// false (default): <name>-<timestamp>-<reason>.log
// true: <name>.log-<timestamp>-<reason>
AppendTimeAfterExt bool `json:"appendTimeAfterExt" yaml:"appendTimeAfterExt"`
// FileMode sets the permissions to use when creating new log files.
// It will be inherited by rotated files.
// If zero, the default of 0o640 is used.
//
// Note that a local umask may alter the final permissions.
// Also, on non-Linux systems this might not have the desired effect.
FileMode os.FileMode `json:"filemode" yaml:"filemode"`
// contains filtered or unexported fields
}
Logger is an io.WriteCloser that writes to the specified filename.
Logger opens or creates the logfile on the first Write. If the file exists and is smaller than MaxSize megabytes, timberjack will open and append to that file. If the file's size exceeds MaxSize, or if the configured RotationInterval has elapsed since the last rotation, the file is closed, renamed with a timestamp, and a new logfile is created using the original filename.
Thus, the filename you give Logger is always the "current" log file.
Backups use the log file name given to Logger, in the form: `name-timestamp-<reason>.ext` where `name` is the filename without the extension, `timestamp` is the time of rotation formatted as `2006-01-02T15-04-05.000`, `reason` is "size" or "time" (Rotate/auto), or a custom tag (RotateWithReason), and `ext` is the original extension. For example, if your Logger.Filename is `/var/log/foo/server.log`, a backup created at 6:30pm on Nov 11 2016 due to size would use the filename `/var/log/foo/server-2016-11-04T18-30-00.000-size.log`.
Cleaning Up Old Log Files ¶
Whenever a new logfile is created, old log files may be deleted based on MaxBackups and MaxAge. The most recent files (according to the timestamp) will be retained up to MaxBackups (or all files if MaxBackups is 0). Any files with a timestamp older than MaxAge days are deleted, regardless of MaxBackups. Note that the timestamp is the rotation time, not necessarily the last write time.
If MaxBackups and MaxAge are both 0, no old log files will be deleted.
timberjack assumes only a single process is writing to the log files at a time.
func (*Logger) Close ¶
Close implements io.Closer, and closes the current logfile. It also signals any running goroutines (like scheduled rotation or mill) to stop.
func (*Logger) Rotate ¶
Rotate forces an immediate rotation using the legacy auto-reason logic. (empty reason => "time" if an interval rotation is due, otherwise "size")
Example ¶
Example of how to rotate in response to SIGHUP.
l := &Logger{}
log.SetOutput(l)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP)
go func() {
for {
<-c
l.Rotate()
}
}()
func (*Logger) RotateWithReason ¶ added in v1.3.7
RotateWithReason forces a rotation immediately and tags the backup filename with the provided reason (after sanitization). If the sanitized reason is empty, it falls back to the default behavior used by Rotate(): "time" if an interval rotation is due, otherwise "size".
NOTE: Like Rotate(), this does not modify lastRotationTime. If an interval rotation is already due, a subsequent write may still trigger another interval-based rotation.
func (*Logger) ValidateBackupTimeFormat ¶ added in v1.3.1
ValidateBackupTimeFormat checks if the configured BackupTimeFormat is a valid time layout. While other formats are allowed, it is recommended to follow the standard time layout rules as defined here: https://pkg.go.dev/time#pkg-constants
WARNING: Assumes that BackupTimeFormat value remains constant after initialization.
func (*Logger) Write ¶
Write implements io.Writer. It writes the provided bytes to the current log file. If the log file exceeds MaxSize after writing, or if the configured RotationInterval has elapsed since the last rotation, or if a scheduled rotation time (RotateAtMinutes) has been reached, the file is closed, renamed to include a timestamp, and a new log file is created using the original filename. If the size of a single write exceeds MaxSize, the write is rejected and an error is returned.