Change definition of maxage to make it easier (i.e. possible) to load from a json/yaml/etc
This commit is contained in:
@@ -28,7 +28,7 @@ log.SetOutput(&lumberjack.Logger{
|
||||
NameFormat: time.RFC822 + ".log",
|
||||
MaxSize: lumberjack.Gigabyte,
|
||||
MaxBackups: 3,
|
||||
MaxAge: lumberjack.Week * 4,
|
||||
MaxAge: 28,
|
||||
})
|
||||
```
|
||||
|
||||
@@ -39,9 +39,6 @@ log.SetOutput(&lumberjack.Logger{
|
||||
const (
|
||||
Megabyte = 1024 * 1024
|
||||
Gigabyte = 1024 * Megabyte
|
||||
|
||||
Day = 24 * time.Hour
|
||||
Week = 7 * Day
|
||||
)
|
||||
```
|
||||
|
||||
@@ -62,10 +59,11 @@ type Logger struct {
|
||||
// rolled. It defaults to 100 megabytes.
|
||||
MaxSize int64 `json:"maxsize" yaml:"maxsize"`
|
||||
|
||||
// MaxAge is the maximum time to retain old log files based on
|
||||
// FileInfo.ModTime. The default is not to remove old log files based on
|
||||
// age.
|
||||
MaxAge time.Duration `json:"maxage" yaml:"maxage"`
|
||||
// MaxAge is the maximum number of days to retain old log files based on
|
||||
// FileInfo.ModTime. 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
|
||||
@@ -100,7 +98,7 @@ Whenever a new file gets created, old log files may be deleted. The log file
|
||||
directory is scanned for files that match NameFormat. The most recent files
|
||||
according to their NameFormat date will be retained, up to a number equal to
|
||||
MaxBackups (or all of them if MaxBackups is 0). Any files with a last
|
||||
modified time (based on FileInfo.ModTime) older than MaxAge are deleted,
|
||||
modified time (based on FileInfo.ModTime) older than MaxAge days are deleted,
|
||||
regardless of MaxBackups.
|
||||
|
||||
If MaxBackups and MaxAge are both 0, no old log files will be deleted.
|
||||
|
||||
+1
-1
@@ -35,6 +35,6 @@ func Example() {
|
||||
NameFormat: time.RFC822 + ".log",
|
||||
MaxSize: lumberjack.Gigabyte,
|
||||
MaxBackups: 3,
|
||||
MaxAge: lumberjack.Week * 4,
|
||||
MaxAge: 28,
|
||||
})
|
||||
}
|
||||
|
||||
+22
-14
@@ -30,12 +30,6 @@ const (
|
||||
Megabyte = 1024 * 1024
|
||||
Gigabyte = 1024 * Megabyte
|
||||
|
||||
// Note that lumberjack days and weeks may not exactly conform to calendar
|
||||
// days and weeks due to daylight savings, leap seconds, etc.
|
||||
|
||||
Day = 24 * time.Hour
|
||||
Week = 7 * Day
|
||||
|
||||
defaultNameFormat = "2006-01-02T15-04-05.000.log"
|
||||
defaultMaxSize = 100 * Megabyte
|
||||
)
|
||||
@@ -66,7 +60,7 @@ var _ io.WriteCloser = (*Logger)(nil)
|
||||
// directory is scanned for files that match NameFormat. The most recent files
|
||||
// according to their NameFormat date will be retained, up to a number equal to
|
||||
// MaxBackups (or all of them if MaxBackups is 0). Any files with a last
|
||||
// modified time (based on FileInfo.ModTime) older than MaxAge are deleted,
|
||||
// modified time (based on FileInfo.ModTime) older than MaxAge days are deleted,
|
||||
// regardless of MaxBackups.
|
||||
//
|
||||
// If MaxBackups and MaxAge are both 0, no old log files will be deleted.
|
||||
@@ -83,10 +77,11 @@ type Logger struct {
|
||||
// rolled. It defaults to 100 megabytes.
|
||||
MaxSize int64 `json:"maxsize" yaml:"maxsize"`
|
||||
|
||||
// MaxAge is the maximum time to retain old log files based on
|
||||
// FileInfo.ModTime. The default is not to remove old log files based on
|
||||
// age.
|
||||
MaxAge time.Duration `json:"maxage" yaml:"maxage"`
|
||||
// MaxAge is the maximum number of days to retain old log files based on
|
||||
// FileInfo.ModTime. 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
|
||||
@@ -102,8 +97,14 @@ type Logger struct {
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// currentTime is only used for testing. Normally it's the time.Now() function.
|
||||
var currentTime = time.Now
|
||||
var (
|
||||
// currentTime exists so it can be mocked out by tests.
|
||||
currentTime = time.Now
|
||||
|
||||
// day is the units that MaxAge converts into. It is a variable so we can
|
||||
// change it during tests.
|
||||
day = 24 * time.Hour
|
||||
)
|
||||
|
||||
// Write implements io.Writer. If a write would cause the log file to be larger
|
||||
// than MaxSize, a new log file is created using the current time formatted with
|
||||
@@ -269,7 +270,9 @@ func (l *Logger) cleanup() error {
|
||||
files = files[:l.MaxBackups]
|
||||
}
|
||||
if l.MaxAge > 0 {
|
||||
cutoff := currentTime().Add(-1 * l.MaxAge)
|
||||
diff := time.Duration(-1 * int64(day) * int64(l.MaxAge))
|
||||
|
||||
cutoff := currentTime().Add(diff)
|
||||
|
||||
for _, f := range files {
|
||||
if f.ModTime().Before(cutoff) {
|
||||
@@ -322,11 +325,14 @@ func (l *Logger) oldLogFiles() ([]os.FileInfo, error) {
|
||||
return logFiles, nil
|
||||
}
|
||||
|
||||
// isLogFile reports where the name of f fits the format of a logfile created by
|
||||
// this Logger.
|
||||
func (l *Logger) isLogFile(f os.FileInfo) bool {
|
||||
_, err := time.Parse(l.format(), filepath.Base(f.Name()))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// max returns the maximum size of log files before rolling..
|
||||
func (l *Logger) max() int64 {
|
||||
if l.MaxSize == 0 {
|
||||
return defaultMaxSize
|
||||
@@ -334,6 +340,7 @@ func (l *Logger) max() int64 {
|
||||
return l.MaxSize
|
||||
}
|
||||
|
||||
// dir returns the directory in which log files should be stored.
|
||||
func (l *Logger) dir() string {
|
||||
if l.Dir != "" {
|
||||
return l.Dir
|
||||
@@ -341,6 +348,7 @@ func (l *Logger) dir() string {
|
||||
return os.TempDir()
|
||||
}
|
||||
|
||||
// format returns the name format for log files.
|
||||
func (l *Logger) format() string {
|
||||
if l.NameFormat != "" {
|
||||
return l.NameFormat
|
||||
|
||||
+39
-16
@@ -1,6 +1,7 @@
|
||||
package lumberjack
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -166,7 +167,7 @@ func TestAutoRotate(t *testing.T) {
|
||||
fileCount(dir, 1, t)
|
||||
|
||||
// set the current time one day later
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
b2 := []byte("foooooo!")
|
||||
n, err = l.Write(b2)
|
||||
@@ -200,7 +201,7 @@ func TestFirstWriteRotate(t *testing.T) {
|
||||
isNil(err, t)
|
||||
|
||||
// set the current time one day later
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
// this would make us rotate
|
||||
b := []byte("fooo!")
|
||||
@@ -236,7 +237,7 @@ func TestMaxBackups(t *testing.T) {
|
||||
fileCount(dir, 1, t)
|
||||
|
||||
// set the current time one day later
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
// this will put us over the max
|
||||
b2 := []byte("foooooo!")
|
||||
@@ -254,7 +255,7 @@ func TestMaxBackups(t *testing.T) {
|
||||
fileCount(dir, 2, t)
|
||||
|
||||
// set the current time one day later
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
// this will make us rotate again
|
||||
n, err = l.Write(b2)
|
||||
@@ -281,7 +282,7 @@ func TestMaxBackups(t *testing.T) {
|
||||
// now test that we don't delete directories or non-logfile files
|
||||
|
||||
// set the current time one day later
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
// create a file that is close to but different from the logfile name.
|
||||
/// It shouldn't get caught by our deletion filters.
|
||||
@@ -295,7 +296,7 @@ func TestMaxBackups(t *testing.T) {
|
||||
err = os.Mkdir(notlogfiledir, 0700)
|
||||
isNil(err, t)
|
||||
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
// this will make us rotate again
|
||||
n, err = l.Write(b2)
|
||||
@@ -329,6 +330,10 @@ func TestMaxBackups(t *testing.T) {
|
||||
|
||||
func TestMaxAge(t *testing.T) {
|
||||
currentTime = fakeTime
|
||||
|
||||
// change how maxage is interpreted from days to milliseconds
|
||||
day = time.Millisecond
|
||||
|
||||
// This test uses ModTime on files, and so we need to make sure we're using
|
||||
// the most current time possible.
|
||||
fakeCurrentTime = time.Now()
|
||||
@@ -339,7 +344,7 @@ func TestMaxAge(t *testing.T) {
|
||||
Dir: dir,
|
||||
NameFormat: format,
|
||||
MaxSize: 10,
|
||||
MaxAge: 10 * time.Millisecond,
|
||||
MaxAge: 10,
|
||||
}
|
||||
defer l.Close()
|
||||
b := []byte("boo!")
|
||||
@@ -415,7 +420,7 @@ func TestDefaultDirAndName(t *testing.T) {
|
||||
err = l.Close()
|
||||
isNil(err, t)
|
||||
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
// even though the old file is under MaxSize, we should write a new file
|
||||
// to prevent two processes using lumberjack from writing to the same file.
|
||||
@@ -452,7 +457,7 @@ func TestRotate(t *testing.T) {
|
||||
fileCount(dir, 1, t)
|
||||
|
||||
// set the current time one day later
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
err = l.Rotate()
|
||||
isNil(err, t)
|
||||
@@ -467,7 +472,7 @@ func TestRotate(t *testing.T) {
|
||||
fileCount(dir, 2, t)
|
||||
|
||||
// set the current time one day later
|
||||
defer newFakeTime(Day)()
|
||||
newFakeTime()
|
||||
|
||||
err = l.Rotate()
|
||||
isNil(err, t)
|
||||
@@ -490,6 +495,28 @@ func TestRotate(t *testing.T) {
|
||||
existsWithLen(filename3, n, t)
|
||||
}
|
||||
|
||||
func TestUnmarshal(t *testing.T) {
|
||||
data := []byte(`
|
||||
{
|
||||
"dir": "foo",
|
||||
"nameformat": "bar",
|
||||
"maxsize": 5,
|
||||
"maxage": 10,
|
||||
"maxbackups": 3,
|
||||
"localtime": true
|
||||
}`[1:])
|
||||
|
||||
l := Logger{}
|
||||
err := json.Unmarshal(data, &l)
|
||||
isNil(err, t)
|
||||
equals("foo", l.Dir, t)
|
||||
equals("bar", l.NameFormat, t)
|
||||
equals(int64(5), l.MaxSize, t)
|
||||
equals(10, l.MaxAge, t)
|
||||
equals(3, l.MaxBackups, t)
|
||||
equals(true, l.LocalTime, t)
|
||||
}
|
||||
|
||||
// makeTempDir creates a file with a semi-unique name in the OS temp directory.
|
||||
// It should be based on the name of the test, to keep parallel tests from
|
||||
// colliding, and must be cleaned up after the test is finished.
|
||||
@@ -528,12 +555,8 @@ func fileCount(dir string, exp int, t testing.TB) {
|
||||
}
|
||||
|
||||
// newFakeTime sets the fake "current time" to one day later.
|
||||
func newFakeTime(later time.Duration) func() {
|
||||
old := fakeCurrentTime
|
||||
fakeCurrentTime = fakeCurrentTime.Add(later)
|
||||
return func() {
|
||||
fakeCurrentTime = old
|
||||
}
|
||||
func newFakeTime() {
|
||||
fakeCurrentTime = fakeCurrentTime.Add(time.Hour * 24)
|
||||
}
|
||||
|
||||
func notExist(path string, t testing.TB) {
|
||||
|
||||
Reference in New Issue
Block a user