Skip to content

Commit

Permalink
🐛 fix: fix the rotating file name is error on use rotatefile.EveryDay…
Browse files Browse the repository at this point in the history
…. see issues #138
  • Loading branch information
inhere committed Mar 26, 2024
1 parent e492570 commit 86e029f
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 32 deletions.
21 changes: 10 additions & 11 deletions rotatefile/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const (
// - "error.log.20201223_1523"
type RotateTime int

// built in rotate time consts
// built in rotate time constants
const (
EveryDay RotateTime = timex.OneDaySec
EveryHour RotateTime = timex.OneHourSec
Expand All @@ -39,38 +39,37 @@ const (
EverySecond RotateTime = 1 // only use for tests
)

// Interval get check interval time
// Interval get check interval time. unit is seconds.
func (rt RotateTime) Interval() int64 {
return int64(rt)
}

// FirstCheckTime for rotate file.
// will automatically align the time from the start of each hour.
func (rt RotateTime) FirstCheckTime(now time.Time) int64 {
// - will automatically align the time from the start of each hour.
func (rt RotateTime) FirstCheckTime(now time.Time) time.Time {
interval := rt.Interval()

switch rt.level() {
case levelDay:
return timex.DayEnd(now).Unix()
return timex.DayEnd(now)
case levelHour:
// should check on H:59:59.500
return timex.HourStart(now).Add(timex.OneHour - 500*time.Millisecond).Unix()
return timex.HourStart(now).Add(timex.OneHour - 500*time.Millisecond)
case levelMin:
// eg: minutes=5
minutes := int(interval / 60)
nextMin := now.Minute() + minutes

// eg: now.Minute()=57, nextMin=62.
// will rotate at next hour start.
// will rotate at next hour start. eg: now.Minute()=57, nextMin=62.
if nextMin >= 60 {
return timex.HourStart(now).Add(timex.OneHour).Unix()
return timex.HourStart(now).Add(timex.OneHour)
}

// eg: now.Minute()=37, nextMin=42, will get nextDur=40
nextDur := time.Duration(nextMin).Round(time.Duration(minutes))
return timex.HourStart(now).Add(nextDur).Unix()
return timex.HourStart(now).Add(nextDur)
default: // levelSec
return now.Unix() + interval
return now.Add(time.Duration(interval) * time.Second)
}
}

Expand Down
6 changes: 3 additions & 3 deletions rotatefile/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,20 @@ func TestRotateTime_TimeFormat(t *testing.T) {
rt := rotatefile.EveryDay
assert.Eq(t, "20060102", rt.TimeFormat())
ft := rt.FirstCheckTime(now.T())
assert.Eq(t, now.DayEnd().Unix(), ft)
assert.True(t, now.DayEnd().Equal(ft))

rt = rotatefile.EveryHour
assert.Eq(t, "20060102_1500", rt.TimeFormat())

rt = rotatefile.Every15Min
assert.Eq(t, "20060102_1504", rt.TimeFormat())
ft = rt.FirstCheckTime(now.T())
assert.Gt(t, ft, 0)
assert.Gt(t, ft.Unix(), 0)

rt = rotatefile.EverySecond
assert.Eq(t, "20060102_150405", rt.TimeFormat())
ft = rt.FirstCheckTime(now.T())
assert.Eq(t, now.Unix()+rt.Interval(), ft)
assert.Eq(t, now.Unix()+rt.Interval(), ft.Unix())
}

func TestRotateTime_String(t *testing.T) {
Expand Down
14 changes: 7 additions & 7 deletions rotatefile/issues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
func TestIssues_138(t *testing.T) {
logfile := "testdata/rotate_day.log"

mt := newMockTime("2023-11-16 23:59:58")
mt := newMockTime("2023-11-16 23:59:55")
w, err := rotatefile.NewWriterWith(rotatefile.WithDebugMode, func(c *rotatefile.Config) {
c.TimeClock = mt
// c.MaxSize = 128
Expand All @@ -26,11 +26,13 @@ func TestIssues_138(t *testing.T) {
assert.NoErr(t, err)
defer w.MustClose()

for i := 0; i < 5; i++ {
for i := 0; i < 15; i++ {
dt := mt.Datetime()
_, err = w.WriteString(dt + " [INFO] this is a log message, idx=" + mathutil.String(i) + "\n")
assert.NoErr(t, err)
mt.Add(time.Second) // add one second
// increase time
mt.Add(time.Second * 3)
// mt.Add(time.Millisecond * 300)
}

// Out: rotate_day.log, rotate_day.log.20231116
Expand All @@ -40,12 +42,10 @@ func TestIssues_138(t *testing.T) {
// check contents
assert.True(t, fsutil.IsFile(logfile))
s := fsutil.ReadString(logfile)
assert.StrContains(t, s, "2023-11-17 00:00:01 [INFO]")
assert.StrNoContains(t, s, "2023-11-16")
assert.StrContains(t, s, "2023-11-17 00:00")

oldFile := logfile + ".20231116"
assert.True(t, fsutil.IsFile(oldFile))
s = fsutil.ReadString(oldFile)
assert.StrContains(t, s, "2023-11-16 23:59:59 [INFO]")
assert.StrNoContains(t, s, "2023-11-17")
assert.StrContains(t, s, "2023-11-16 23:")
}
21 changes: 10 additions & 11 deletions rotatefile/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ type Writer struct {
rotateNum uint // rotate times number

// context use for rotating file by time
suffixFormat string // the rotating file name suffix. eg: "20210102", "20210102_1500"
checkInterval int64 // check interval seconds.
nextRotatingAt int64
suffixFormat string // the rotating file name suffix. eg: "20210102", "20210102_1500"
checkInterval int64 // check interval seconds.
nextRotatingAt time.Time // next rotating time
}

// NewWriter create rotate write with config and init it.
Expand Down Expand Up @@ -74,12 +74,11 @@ func (d *Writer) init() error {

// calc and storage next rotating time
if d.checkInterval > 0 {
nowTime := d.cfg.TimeClock.Now()
now := d.cfg.TimeClock.Now()
// next rotating time
d.nextRotatingAt = d.cfg.RotateTime.FirstCheckTime(nowTime)

d.nextRotatingAt = d.cfg.RotateTime.FirstCheckTime(now)
if d.cfg.RotateMode == ModeCreate {
logfile = d.cfg.Filepath + "." + nowTime.Format(d.suffixFormat)
logfile = d.cfg.Filepath + "." + now.Format(d.suffixFormat)
}
}

Expand Down Expand Up @@ -185,17 +184,17 @@ func (d *Writer) doRotate() (err error) {
// TIP: should only call on d.checkInterval > 0
func (d *Writer) rotatingByTime() error {
now := d.cfg.TimeClock.Now()
if d.nextRotatingAt > now.Unix() {
if now.Before(d.nextRotatingAt) {
return nil
}

// generate new file path.
// eg: /tmp/error.log => /tmp/error.log.20220423_1600
file := d.cfg.Filepath + "." + now.Format(d.suffixFormat)
file := d.cfg.Filepath + "." + d.nextRotatingAt.Format(d.suffixFormat)
err := d.rotatingFile(file, false)

// storage next rotating time
d.nextRotatingAt = now.Unix() + d.checkInterval
// calc and storage next rotating time
d.nextRotatingAt = d.nextRotatingAt.Add(time.Duration(d.checkInterval) * time.Second)
return err
}

Expand Down

0 comments on commit 86e029f

Please sign in to comment.