Skip to content

Commit 90bbf12

Browse files
committed
Support split log file by date
1 parent a4a1dc5 commit 90bbf12

File tree

4 files changed

+85
-12
lines changed

4 files changed

+85
-12
lines changed

file_logger.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ var (
2525
mkdirAll = os.MkdirAll
2626
create = os.Create
2727
openFile = os.OpenFile
28+
now = time.Now
2829
)
2930

3031
type fileLogger struct {
@@ -38,6 +39,7 @@ type fileLogger struct {
3839
close chan struct{} // the log is closed, and wait to write all the logs
3940
mu sync.Mutex // avoid data race for writer
4041
date time.Time
42+
file *os.File
4143
}
4244

4345
type logMsg struct {
@@ -89,30 +91,32 @@ func (l *fileLogger) Close() error {
8991
}
9092

9193
func (l *fileLogger) init() error {
92-
if err := l.initFile(); err != nil {
94+
if err := l.initFile(true); err != nil {
9395
return err
9496
}
9597
l.start()
9698
l.startAutoFlush()
9799
return nil
98100
}
99101

100-
func (l *fileLogger) initFile() error {
101-
now := time.Now()
102+
func (l *fileLogger) initFile(splitDate bool) error {
103+
if !splitDate {
104+
return nil
105+
}
106+
date := now()
102107
timeFormat := "20060102"
103-
if l.date.Format(timeFormat) == now.Format(timeFormat) {
108+
if l.date.Format(timeFormat) == date.Format(timeFormat) {
104109
return nil
105110
}
106111
// reset initialized
107112
l.initialized = false
108-
l.date = now
109113

110114
logDir := filepath.Clean(l.opt.LogDir)
111115
prefix := strings.TrimSpace(l.opt.FilePrefix)
112116
if len(prefix) > 0 {
113117
prefix = filepath.Clean(prefix)
114118
}
115-
logFile := logDir + "/" + prefix + l.date.Format(timeFormat) + ".log"
119+
logFile := logDir + "/" + prefix + date.Format(timeFormat) + ".log"
116120

117121
_, err := stat(logDir)
118122
if isNotExist(err) {
@@ -135,8 +139,21 @@ func (l *fileLogger) initFile() error {
135139
l.innerLog("init file logger err, can't open the log file. %s", err)
136140
return err
137141
}
142+
143+
if l.writer != nil {
144+
l.writer.Flush()
145+
}
146+
138147
l.writer = newWriter(f)
139148
l.initialized = true
149+
l.date = date
150+
151+
if l.file != nil {
152+
if err = l.file.Close(); err != nil {
153+
l.innerLog("close file error => %s %v", l.file.Name(), err)
154+
}
155+
}
156+
l.file = f
140157
return nil
141158
}
142159

@@ -157,6 +174,7 @@ func (l *fileLogger) write() {
157174
if msg.closed {
158175
if l.initialized && l.writer != nil {
159176
l.writer.Flush()
177+
l.file.Close()
160178
}
161179
l.close <- struct{}{}
162180
} else if msg.flush && l.initialized && l.writer != nil && l.writer.Buffered() > 0 {
@@ -165,6 +183,10 @@ func (l *fileLogger) write() {
165183
l.innerLog("file logger flush log error. %s", err)
166184
}
167185
} else if l.initialized && l.writer != nil && len(msg.log) > 0 {
186+
if err := l.initFile(l.opt.SplitDate); err != nil {
187+
l.innerLog("init log file error. %s", err)
188+
return
189+
}
168190
if _, err := l.writer.Write(msg.log); err != nil {
169191
l.innerLog("file logger write log error. %s", err)
170192
}
@@ -187,7 +209,7 @@ func (l *fileLogger) startAutoFlush() {
187209
delayCheckCount := 10
188210
for {
189211
<-time.After(wait)
190-
if l.closed.Get() || l.writer == nil {
212+
if l.closed.Get() {
191213
return
192214
}
193215
l.mu.Lock()
@@ -217,7 +239,7 @@ func (l *fileLogger) Write(p []byte) (n int, err error) {
217239
}
218240
cp := make([]byte, pLen)
219241
copy(cp, p)
220-
if l.initialized && !l.closed.Get() {
242+
if !l.closed.Get() {
221243
l.in <- logMsg{
222244
log: cp,
223245
closed: false,

file_logger_mock_test.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/no-src/log/level"
15+
"github.com/no-src/log/option"
1516
)
1617

1718
func TestFileLogger_WithNotExistFile(t *testing.T) {
@@ -96,6 +97,42 @@ func TestFileLogger_WithAutoFlushWithWriteErrorAndNoAutoFlush(t *testing.T) {
9697
<-time.After(wait + time.Second)
9798
}
9899

100+
func TestFileLogger_WithMultiInitFile(t *testing.T) {
101+
defer func() {
102+
initTimeMock()
103+
}()
104+
fLogger, err := NewFileLogger(level.DebugLevel, "./multi_init_file_logs", "ns")
105+
if err != nil {
106+
t.Fatal(err)
107+
}
108+
now = nowMock
109+
fLogger.(*fileLogger).initFile(true)
110+
InitDefaultLogger(fLogger)
111+
defer Close()
112+
}
113+
114+
func TestFileLogger_WithSplitDateError(t *testing.T) {
115+
defer func() {
116+
initTimeMock()
117+
initOSMock()
118+
}()
119+
fLogger, err := NewFileLoggerWithOption(option.FileLoggerOption{
120+
Level: level.DebugLevel,
121+
LogDir: "./split_date_logs_error",
122+
FilePrefix: "ns",
123+
SplitDate: true,
124+
})
125+
if err != nil {
126+
t.Fatal(err)
127+
}
128+
InitDefaultLogger(fLogger)
129+
defer Close()
130+
isNotExist = isNotExistAlwaysTrueMock
131+
mkdirAll = mkdirAllErrorMock
132+
now = nowMock
133+
testLogs(t)
134+
}
135+
99136
func init() {
100137
initFileLoggerMock()
101138
}
@@ -131,6 +168,10 @@ func initOSMock() {
131168
openFile = openFileMock
132169
}
133170

171+
func initTimeMock() {
172+
now = time.Now
173+
}
174+
134175
func isNotExistAlwaysFalseMock(err error) bool {
135176
return false
136177
}
@@ -156,9 +197,13 @@ func createErrorMock(name string) (*os.File, error) {
156197
}
157198

158199
func openFileMock(name string, flag int, perm os.FileMode) (*os.File, error) {
159-
return nil, nil
200+
return os.Stdout, nil
160201
}
161202

162203
func openFileErrorMock(name string, flag int, perm os.FileMode) (*os.File, error) {
163204
return nil, errors.New("the OpenFile error test")
164205
}
206+
207+
func nowMock() time.Time {
208+
return time.Now().Add(time.Hour * 24)
209+
}

file_logger_test.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/no-src/log/formatter"
88
"github.com/no-src/log/level"
9+
"github.com/no-src/log/option"
910
)
1011

1112
func TestFileLogger(t *testing.T) {
@@ -81,12 +82,16 @@ func TestConsoleLoggerAndFileLogger(t *testing.T) {
8182
testLogs(t)
8283
}
8384

84-
func TestFileLogger_WithMultiInitFile(t *testing.T) {
85-
fLogger, err := NewFileLogger(level.DebugLevel, "./multi_init_file_logs", "ns")
85+
func TestFileLogger_WithSplitDate(t *testing.T) {
86+
fLogger, err := NewFileLoggerWithOption(option.FileLoggerOption{
87+
Level: level.DebugLevel,
88+
LogDir: "./split_date_logs",
89+
FilePrefix: "ns",
90+
SplitDate: true,
91+
})
8692
if err != nil {
8793
t.Fatal(err)
8894
}
89-
fLogger.(*fileLogger).initFile()
9095
InitDefaultLogger(fLogger)
9196
defer Close()
9297
testLogs(t)

option/file_logger_option.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ type FileLoggerOption struct {
1313
FilePrefix string
1414
AutoFlush bool
1515
FlushInterval time.Duration
16+
SplitDate bool
1617
}

0 commit comments

Comments
 (0)