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",
|
NameFormat: time.RFC822 + ".log",
|
||||||
MaxSize: lumberjack.Gigabyte,
|
MaxSize: lumberjack.Gigabyte,
|
||||||
MaxBackups: 3,
|
MaxBackups: 3,
|
||||||
MaxAge: lumberjack.Week * 4,
|
MaxAge: 28,
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -39,9 +39,6 @@ log.SetOutput(&lumberjack.Logger{
|
|||||||
const (
|
const (
|
||||||
Megabyte = 1024 * 1024
|
Megabyte = 1024 * 1024
|
||||||
Gigabyte = 1024 * Megabyte
|
Gigabyte = 1024 * Megabyte
|
||||||
|
|
||||||
Day = 24 * time.Hour
|
|
||||||
Week = 7 * Day
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -62,10 +59,11 @@ type Logger struct {
|
|||||||
// rolled. It defaults to 100 megabytes.
|
// rolled. It defaults to 100 megabytes.
|
||||||
MaxSize int64 `json:"maxsize" yaml:"maxsize"`
|
MaxSize int64 `json:"maxsize" yaml:"maxsize"`
|
||||||
|
|
||||||
// MaxAge is the maximum time to retain old log files based on
|
// MaxAge is the maximum number of days to retain old log files based on
|
||||||
// FileInfo.ModTime. The default is not to remove old log files based on
|
// FileInfo.ModTime. Note that a day is defined as 24 hours and may not
|
||||||
// age.
|
// exactly correspond to calendar days due to daylight savings, leap
|
||||||
MaxAge time.Duration `json:"maxage" yaml:"maxage"`
|
// 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
|
// 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
|
// 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
|
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
|
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
|
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.
|
regardless of MaxBackups.
|
||||||
|
|
||||||
If MaxBackups and MaxAge are both 0, no old log files will be deleted.
|
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",
|
NameFormat: time.RFC822 + ".log",
|
||||||
MaxSize: lumberjack.Gigabyte,
|
MaxSize: lumberjack.Gigabyte,
|
||||||
MaxBackups: 3,
|
MaxBackups: 3,
|
||||||
MaxAge: lumberjack.Week * 4,
|
MaxAge: 28,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-14
@@ -30,12 +30,6 @@ const (
|
|||||||
Megabyte = 1024 * 1024
|
Megabyte = 1024 * 1024
|
||||||
Gigabyte = 1024 * Megabyte
|
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"
|
defaultNameFormat = "2006-01-02T15-04-05.000.log"
|
||||||
defaultMaxSize = 100 * Megabyte
|
defaultMaxSize = 100 * Megabyte
|
||||||
)
|
)
|
||||||
@@ -66,7 +60,7 @@ var _ io.WriteCloser = (*Logger)(nil)
|
|||||||
// directory is scanned for files that match NameFormat. The most recent files
|
// 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
|
// 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
|
// 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.
|
// regardless of MaxBackups.
|
||||||
//
|
//
|
||||||
// If MaxBackups and MaxAge are both 0, no old log files will be deleted.
|
// 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.
|
// rolled. It defaults to 100 megabytes.
|
||||||
MaxSize int64 `json:"maxsize" yaml:"maxsize"`
|
MaxSize int64 `json:"maxsize" yaml:"maxsize"`
|
||||||
|
|
||||||
// MaxAge is the maximum time to retain old log files based on
|
// MaxAge is the maximum number of days to retain old log files based on
|
||||||
// FileInfo.ModTime. The default is not to remove old log files based on
|
// FileInfo.ModTime. Note that a day is defined as 24 hours and may not
|
||||||
// age.
|
// exactly correspond to calendar days due to daylight savings, leap
|
||||||
MaxAge time.Duration `json:"maxage" yaml:"maxage"`
|
// 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
|
// 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
|
// 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
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// currentTime is only used for testing. Normally it's the time.Now() function.
|
var (
|
||||||
var currentTime = time.Now
|
// 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
|
// 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
|
// 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]
|
files = files[:l.MaxBackups]
|
||||||
}
|
}
|
||||||
if l.MaxAge > 0 {
|
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 {
|
for _, f := range files {
|
||||||
if f.ModTime().Before(cutoff) {
|
if f.ModTime().Before(cutoff) {
|
||||||
@@ -322,11 +325,14 @@ func (l *Logger) oldLogFiles() ([]os.FileInfo, error) {
|
|||||||
return logFiles, nil
|
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 {
|
func (l *Logger) isLogFile(f os.FileInfo) bool {
|
||||||
_, err := time.Parse(l.format(), filepath.Base(f.Name()))
|
_, err := time.Parse(l.format(), filepath.Base(f.Name()))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// max returns the maximum size of log files before rolling..
|
||||||
func (l *Logger) max() int64 {
|
func (l *Logger) max() int64 {
|
||||||
if l.MaxSize == 0 {
|
if l.MaxSize == 0 {
|
||||||
return defaultMaxSize
|
return defaultMaxSize
|
||||||
@@ -334,6 +340,7 @@ func (l *Logger) max() int64 {
|
|||||||
return l.MaxSize
|
return l.MaxSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dir returns the directory in which log files should be stored.
|
||||||
func (l *Logger) dir() string {
|
func (l *Logger) dir() string {
|
||||||
if l.Dir != "" {
|
if l.Dir != "" {
|
||||||
return l.Dir
|
return l.Dir
|
||||||
@@ -341,6 +348,7 @@ func (l *Logger) dir() string {
|
|||||||
return os.TempDir()
|
return os.TempDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// format returns the name format for log files.
|
||||||
func (l *Logger) format() string {
|
func (l *Logger) format() string {
|
||||||
if l.NameFormat != "" {
|
if l.NameFormat != "" {
|
||||||
return l.NameFormat
|
return l.NameFormat
|
||||||
|
|||||||
+39
-16
@@ -1,6 +1,7 @@
|
|||||||
package lumberjack
|
package lumberjack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -166,7 +167,7 @@ func TestAutoRotate(t *testing.T) {
|
|||||||
fileCount(dir, 1, t)
|
fileCount(dir, 1, t)
|
||||||
|
|
||||||
// set the current time one day later
|
// set the current time one day later
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
b2 := []byte("foooooo!")
|
b2 := []byte("foooooo!")
|
||||||
n, err = l.Write(b2)
|
n, err = l.Write(b2)
|
||||||
@@ -200,7 +201,7 @@ func TestFirstWriteRotate(t *testing.T) {
|
|||||||
isNil(err, t)
|
isNil(err, t)
|
||||||
|
|
||||||
// set the current time one day later
|
// set the current time one day later
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
// this would make us rotate
|
// this would make us rotate
|
||||||
b := []byte("fooo!")
|
b := []byte("fooo!")
|
||||||
@@ -236,7 +237,7 @@ func TestMaxBackups(t *testing.T) {
|
|||||||
fileCount(dir, 1, t)
|
fileCount(dir, 1, t)
|
||||||
|
|
||||||
// set the current time one day later
|
// set the current time one day later
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
// this will put us over the max
|
// this will put us over the max
|
||||||
b2 := []byte("foooooo!")
|
b2 := []byte("foooooo!")
|
||||||
@@ -254,7 +255,7 @@ func TestMaxBackups(t *testing.T) {
|
|||||||
fileCount(dir, 2, t)
|
fileCount(dir, 2, t)
|
||||||
|
|
||||||
// set the current time one day later
|
// set the current time one day later
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
// this will make us rotate again
|
// this will make us rotate again
|
||||||
n, err = l.Write(b2)
|
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
|
// now test that we don't delete directories or non-logfile files
|
||||||
|
|
||||||
// set the current time one day later
|
// set the current time one day later
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
// create a file that is close to but different from the logfile name.
|
// create a file that is close to but different from the logfile name.
|
||||||
/// It shouldn't get caught by our deletion filters.
|
/// It shouldn't get caught by our deletion filters.
|
||||||
@@ -295,7 +296,7 @@ func TestMaxBackups(t *testing.T) {
|
|||||||
err = os.Mkdir(notlogfiledir, 0700)
|
err = os.Mkdir(notlogfiledir, 0700)
|
||||||
isNil(err, t)
|
isNil(err, t)
|
||||||
|
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
// this will make us rotate again
|
// this will make us rotate again
|
||||||
n, err = l.Write(b2)
|
n, err = l.Write(b2)
|
||||||
@@ -329,6 +330,10 @@ func TestMaxBackups(t *testing.T) {
|
|||||||
|
|
||||||
func TestMaxAge(t *testing.T) {
|
func TestMaxAge(t *testing.T) {
|
||||||
currentTime = fakeTime
|
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
|
// This test uses ModTime on files, and so we need to make sure we're using
|
||||||
// the most current time possible.
|
// the most current time possible.
|
||||||
fakeCurrentTime = time.Now()
|
fakeCurrentTime = time.Now()
|
||||||
@@ -339,7 +344,7 @@ func TestMaxAge(t *testing.T) {
|
|||||||
Dir: dir,
|
Dir: dir,
|
||||||
NameFormat: format,
|
NameFormat: format,
|
||||||
MaxSize: 10,
|
MaxSize: 10,
|
||||||
MaxAge: 10 * time.Millisecond,
|
MaxAge: 10,
|
||||||
}
|
}
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
b := []byte("boo!")
|
b := []byte("boo!")
|
||||||
@@ -415,7 +420,7 @@ func TestDefaultDirAndName(t *testing.T) {
|
|||||||
err = l.Close()
|
err = l.Close()
|
||||||
isNil(err, t)
|
isNil(err, t)
|
||||||
|
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
// even though the old file is under MaxSize, we should write a new file
|
// 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.
|
// 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)
|
fileCount(dir, 1, t)
|
||||||
|
|
||||||
// set the current time one day later
|
// set the current time one day later
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
err = l.Rotate()
|
err = l.Rotate()
|
||||||
isNil(err, t)
|
isNil(err, t)
|
||||||
@@ -467,7 +472,7 @@ func TestRotate(t *testing.T) {
|
|||||||
fileCount(dir, 2, t)
|
fileCount(dir, 2, t)
|
||||||
|
|
||||||
// set the current time one day later
|
// set the current time one day later
|
||||||
defer newFakeTime(Day)()
|
newFakeTime()
|
||||||
|
|
||||||
err = l.Rotate()
|
err = l.Rotate()
|
||||||
isNil(err, t)
|
isNil(err, t)
|
||||||
@@ -490,6 +495,28 @@ func TestRotate(t *testing.T) {
|
|||||||
existsWithLen(filename3, n, 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.
|
// 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
|
// 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.
|
// 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.
|
// newFakeTime sets the fake "current time" to one day later.
|
||||||
func newFakeTime(later time.Duration) func() {
|
func newFakeTime() {
|
||||||
old := fakeCurrentTime
|
fakeCurrentTime = fakeCurrentTime.Add(time.Hour * 24)
|
||||||
fakeCurrentTime = fakeCurrentTime.Add(later)
|
|
||||||
return func() {
|
|
||||||
fakeCurrentTime = old
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func notExist(path string, t testing.TB) {
|
func notExist(path string, t testing.TB) {
|
||||||
|
|||||||
Reference in New Issue
Block a user