@@ -3,6 +3,8 @@ package logging
3
3
import (
4
4
"fmt"
5
5
"os"
6
+ "sync"
7
+ "time"
6
8
)
7
9
8
10
// Check whether the specified directory/file exists or not.
@@ -71,12 +73,20 @@ func (self *BaseRotatingHandler) RolloverEmit(
71
73
return nil
72
74
}
73
75
76
+ type HandleFunc func (record * LogRecord ) int
77
+
74
78
// Handler for logging to a set of files, which switches from one file to
75
79
// the next when the current file reaches a certain size.
76
80
type RotatingFileHandler struct {
77
81
* BaseRotatingHandler
78
- maxBytes uint64
79
- backupCount uint32
82
+ maxBytes uint64
83
+ backupCount uint32
84
+ bufferFlushTime time.Duration
85
+ inputChanSize int
86
+ handleFunc HandleFunc
87
+ inputChan chan * LogRecord
88
+ exitChan chan int
89
+ group * sync.WaitGroup
80
90
}
81
91
82
92
// Open the specified file and use it as the stream for logging.
@@ -96,10 +106,22 @@ type RotatingFileHandler struct {
96
106
// "app.log.3" etc. respectively.
97
107
//
98
108
// If maxBytes is zero, rollover never occurs.
109
+ //
110
+ // bufferSize specifies the size of the internal buffer. If it is positive,
111
+ // the internal buffer will be enabled, the logs will be first written into
112
+ // the internal buffer, when the internal buffer is full all buffer content
113
+ // will be flushed to file.
114
+ // bufferFlushTime specifies the time for flushing the internal buffer
115
+ // in period, no matter the buffer is full or not.
116
+ // inputChanSize specifies the chan size of the handler. If it is positive,
117
+ // this handler will be initialized as a standardlone go routine to handle
118
+ // log message.
99
119
func NewRotatingFileHandler (
100
120
filepath string ,
101
121
mode int ,
102
122
bufferSize int ,
123
+ bufferFlushTime time.Duration ,
124
+ inputChanSize int ,
103
125
maxBytes uint64 ,
104
126
backupCount uint32 ) (* RotatingFileHandler , error ) {
105
127
@@ -119,6 +141,21 @@ func NewRotatingFileHandler(
119
141
BaseRotatingHandler : base ,
120
142
maxBytes : maxBytes ,
121
143
backupCount : backupCount ,
144
+ bufferFlushTime : bufferFlushTime ,
145
+ inputChanSize : inputChanSize ,
146
+ }
147
+ if inputChanSize > 0 {
148
+ object .handleFunc = object .handleChan
149
+ object .inputChan = make (chan * LogRecord , inputChanSize )
150
+ object .exitChan = make (chan int , 1 )
151
+ object .group = & sync.WaitGroup {}
152
+ object .group .Add (1 )
153
+ go func () {
154
+ defer object .group .Done ()
155
+ object .loop ()
156
+ }()
157
+ } else {
158
+ object .handleFunc = object .handleCall
122
159
}
123
160
return object , nil
124
161
}
@@ -127,11 +164,19 @@ func MustNewRotatingFileHandler(
127
164
filepath string ,
128
165
mode int ,
129
166
bufferSize int ,
167
+ bufferFlushTime time.Duration ,
168
+ inputChanSize int ,
130
169
maxBytes uint64 ,
131
170
backupCount uint32 ) * RotatingFileHandler {
132
171
133
172
handler , err := NewRotatingFileHandler (
134
- filepath , mode , bufferSize , maxBytes , backupCount )
173
+ filepath ,
174
+ mode ,
175
+ bufferSize ,
176
+ bufferFlushTime ,
177
+ inputChanSize ,
178
+ maxBytes ,
179
+ backupCount )
135
180
if err != nil {
136
181
panic ("NewRotatingFileHandler(), error: " + err .Error ())
137
182
}
@@ -175,9 +220,9 @@ func (self *RotatingFileHandler) RotateFile(sourceFile, destFile string) error {
175
220
176
221
// Do a rollover, as described above.
177
222
func (self * RotatingFileHandler ) DoRollover () (err error ) {
178
- self .Close ()
223
+ self .FileHandler . Close ()
179
224
defer func () {
180
- if e := self .Open (); e != nil {
225
+ if e := self .FileHandler . Open (); e != nil {
181
226
if e == nil {
182
227
err = e
183
228
}
@@ -205,6 +250,37 @@ func (self *RotatingFileHandler) Emit(record *LogRecord) error {
205
250
return self .RolloverEmit (self , record )
206
251
}
207
252
208
- func (self * RotatingFileHandler ) Handle (record * LogRecord ) int {
253
+ func (self * RotatingFileHandler ) handleCall (record * LogRecord ) int {
209
254
return self .Handle2 (self , record )
210
255
}
256
+
257
+ func (self * RotatingFileHandler ) handleChan (record * LogRecord ) int {
258
+ self .inputChan <- record
259
+ return 0
260
+ }
261
+
262
+ func (self * RotatingFileHandler ) loop () {
263
+ ticker := time .NewTicker (self .bufferFlushTime )
264
+ for {
265
+ select {
266
+ case r := <- self .inputChan :
267
+ self .Handle2 (self , r )
268
+ case <- self .exitChan :
269
+ return
270
+ case <- ticker .C :
271
+ self .Flush ()
272
+ }
273
+ }
274
+ }
275
+
276
+ func (self * RotatingFileHandler ) Handle (record * LogRecord ) int {
277
+ return self .handleFunc (record )
278
+ }
279
+
280
+ func (self * RotatingFileHandler ) Close () {
281
+ if self .inputChanSize > 0 {
282
+ self .exitChan <- 1
283
+ self .group .Wait ()
284
+ }
285
+ self .BaseRotatingHandler .Close ()
286
+ }
0 commit comments