Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rotate periodically #103

Open
wants to merge 3 commits into
base: v2.0
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions lumberjack.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ const (
defaultMaxSize = 100
)

type PERIOD int

const (
PERIOD_CLOSE PERIOD = iota
PERIOD_MINUTE
PERIOD_HOUR
PERIOD_DAY
)

// ensure we always implement io.WriteCloser
var _ io.WriteCloser = (*Logger)(nil)

Expand Down Expand Up @@ -103,6 +112,11 @@ type Logger struct {
// time.
LocalTime bool `json:"localtime" yaml:"localtime"`

// Period defines how offen the log file will get rotated automatically. 0 = PERIOD_CLOSE(default)
// means not to rotate automatically, PERIOD_MINUTE means ratating every minute,
// PERIOD_HOUR means ratating every hour, PERIOD_DAY or larger means rotating every day.
Period PERIOD `json:"period" yaml:"period"`

// Compress determines if the rotated log files should be compressed
// using gzip. The default is not to perform compression.
Compress bool `json:"compress" yaml:"compress"`
Expand Down Expand Up @@ -388,13 +402,57 @@ func (l *Logger) mill() {
l.startMill.Do(func() {
l.millCh = make(chan bool, 1)
go l.millRun()
go l.periodRotate()
})
select {
case l.millCh <- true:
default:
}
}

// automates rotation periodically
func (l *Logger) periodRotate() {
if l.Period <= PERIOD_CLOSE {
return
}
// period means the frequency to rotate in second.
// We also need to comute next rotate sharp time after the first write.
// For example, we write the first log in 16:09 and we set period 2, so next rotate
// should be in 17:00, 18:00, 19:00, etc.
period := time.Second * 1
duration := 0
timer := currentTime()
currentSecond := timer.Second()
currentMinute := timer.Minute()
currentHour := timer.Hour()
if !l.LocalTime {
currentHour = timer.UTC().Hour()
}
switch l.Period {
case PERIOD_MINUTE:
period *= 60
duration = 60 - currentSecond
case PERIOD_HOUR:
period *= 3600
duration = 3600 - currentMinute*60 - currentSecond
default:
period *= 86400
duration = 86400 - currentHour*3600 - currentMinute*60 - currentSecond
}
if duration > 0 {
time.Sleep(time.Duration(duration) * time.Second)
l.rotate()
}

ticker := time.NewTicker(period)
for {
select {
case <-ticker.C:
l.rotate()
}
}
}

// oldLogFiles returns the list of backup log files stored in the same
// directory as the current log file, sorted by ModTime
func (l *Logger) oldLogFiles() ([]logInfo, error) {
Expand Down