Skip to content

Commit 8f5b8aa

Browse files
lvan100lianghuan
authored andcommitted
111
1 parent 301cde8 commit 8f5b8aa

File tree

3 files changed

+57
-100
lines changed

3 files changed

+57
-100
lines changed

plugin_appender.go

Lines changed: 41 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ func init() {
3737
RegisterPlugin[ConsoleAppender]("Console", PluginTypeAppender)
3838
RegisterPlugin[FileAppender]("File", PluginTypeAppender)
3939
RegisterPlugin[GroupAppender]("Group", PluginTypeAppender)
40+
41+
// register built-in converters
42+
RegisterConverter(ParseRotateStrategy)
43+
44+
// register built-in rotate strategies
45+
RegisterRotateStrategy("1h", FixedRotateStrategy{Interval: time.Hour})
46+
RegisterRotateStrategy("30m", FixedRotateStrategy{Interval: 30 * time.Minute})
47+
RegisterRotateStrategy("10m", FixedRotateStrategy{Interval: 10 * time.Minute})
4048
}
4149

4250
// Appender defines components that handle log output.
@@ -137,64 +145,10 @@ func (c *ConsoleAppender) Write(b []byte) {
137145
_, _ = Stdout.Write(b)
138146
}
139147

140-
// FileAppender writes formatted log events to a specified file.
141-
type FileAppender struct {
142-
AppenderBase
143-
Layout Layout `PluginElement:"Layout,default=TextLayout"`
144-
FileDir string `PluginAttribute:"fileDir,default=./logs"`
145-
FileName string `PluginAttribute:"fileName"`
146-
147-
file *os.File
148-
}
149-
150-
func (c *FileAppender) ConcurrentSafe() bool { return true }
151-
152-
// Start opens the log file for appending.
153-
func (c *FileAppender) Start() error {
154-
const fileFlag = os.O_WRONLY | os.O_CREATE | os.O_APPEND
155-
fileName := filepath.Join(c.FileDir, c.FileName)
156-
f, err := os.OpenFile(fileName, fileFlag, 0644)
157-
if err != nil {
158-
return err
159-
}
160-
c.file = f
161-
return nil
162-
}
163-
164-
// Append formats the log event and writes it to the file.
165-
func (c *FileAppender) Append(e *Event) {
166-
if c.EnableLevel(e.Level) {
167-
c.Write(c.Layout.ToBytes(e))
168-
}
169-
}
170-
171-
// Write writes a byte slice directly to the file.
172-
func (c *FileAppender) Write(b []byte) {
173-
_, _ = c.file.Write(b)
174-
}
175-
176-
// Stop flushes and closes the file.
177-
func (c *FileAppender) Stop() {
178-
if c.file != nil {
179-
_ = c.file.Sync()
180-
_ = c.file.Close()
181-
}
182-
}
183-
184-
func init() {
185-
// register built-in converters
186-
RegisterConverter(ParseRotateStrategy)
187-
188-
// register built-in rotate strategies
189-
RegisterRotateStrategy("1h", FixedRotateStrategy{Interval: time.Hour})
190-
RegisterRotateStrategy("30m", FixedRotateStrategy{Interval: 30 * time.Minute})
191-
RegisterRotateStrategy("10m", FixedRotateStrategy{Interval: 10 * time.Minute})
192-
}
193-
194-
var rotateStrategyRegistry = map[string]RotateStrategy{}
148+
var rotateStrategyRegistry = map[string]RollingPolicy{}
195149

196-
// RotateStrategy defines the interface for log rotation strategies.
197-
type RotateStrategy interface {
150+
// RollingPolicy defines the interface for log rotation strategies.
151+
type RollingPolicy interface {
198152
Time(t time.Time) int64
199153
Format(t time.Time) string
200154
}
@@ -216,20 +170,25 @@ func (r FixedRotateStrategy) Format(t time.Time) string {
216170
}
217171

218172
// RegisterRotateStrategy registers a rotation strategy with a given name.
219-
func RegisterRotateStrategy(name string, strategy RotateStrategy) {
173+
func RegisterRotateStrategy(name string, strategy RollingPolicy) {
220174
rotateStrategyRegistry[name] = strategy
221175
}
222176

177+
var noneRotateStrategy = &FixedRotateStrategy{}
178+
223179
// ParseRotateStrategy retrieves a registered rotation strategy by name.
224-
func ParseRotateStrategy(name string) (RotateStrategy, error) {
180+
func ParseRotateStrategy(name string) (RollingPolicy, error) {
181+
if name == "None" {
182+
return noneRotateStrategy, nil
183+
}
225184
s, ok := rotateStrategyRegistry[name]
226185
if !ok {
227186
return nil, fmt.Errorf("invalid rotate strategy: %q", name)
228187
}
229188
return s, nil
230189
}
231190

232-
// RotateFileAppender allows **multiple goroutines** to call Write()
191+
// FileAppender allows **multiple goroutines** to call Write()
233192
// safely, at the cost of slightly higher overhead and potential
234193
// (acceptable) log loss during rotation.
235194
//
@@ -243,39 +202,42 @@ func ParseRotateStrategy(name string) (RotateStrategy, error) {
243202
// - During Stop(), concurrent writes may also be lost.
244203
// - If zero log loss is required, use AsyncRotateFileWriter
245204
// with a dedicated logging goroutine instead.
246-
type RotateFileAppender struct {
247-
FileDir string
248-
FileName string
249-
ClearHours int32
250-
RotateStrategy RotateStrategy
251-
file atomic.Pointer[os.File]
252-
mutex sync.Mutex
253-
currTime atomic.Int64
205+
type FileAppender struct {
206+
AppenderBase
207+
Layout Layout `PluginElement:"Layout,default=TextLayout"`
208+
FileDir string `PluginAttribute:"fileDir,default=./logs"`
209+
FileName string `PluginAttribute:"fileName"`
210+
211+
ClearHours int32
212+
RollingPolicy RollingPolicy
213+
file atomic.Pointer[os.File]
214+
mutex sync.Mutex
215+
currTime atomic.Int64
254216
}
255217

256218
// Start opens the initial log file.
257-
func (c *RotateFileAppender) Start() error {
219+
func (c *FileAppender) Start() error {
258220
now := time.Now()
259221
filePath, file, err := c.createFile(now)
260222
if err != nil {
261223
return util.WrapError(err, "Failed to create log file %s", filePath)
262224
}
263225
c.file.Store(file)
264-
c.currTime.Store(c.RotateStrategy.Time(now))
226+
c.currTime.Store(c.RollingPolicy.Time(now))
265227
return nil
266228
}
267229

268230
// Write writes bytes to the current log file.
269231
// May lose a few writes during rotation or Stop().
270-
func (c *RotateFileAppender) Write(b []byte) {
232+
func (c *FileAppender) Write(b []byte) {
271233
c.rotate()
272234
if file := c.file.Load(); file != nil {
273235
_, _ = file.Write(b)
274236
}
275237
}
276238

277239
// Stop flushes and closes the current file.
278-
func (c *RotateFileAppender) Stop() {
240+
func (c *FileAppender) Stop() {
279241
c.rotate()
280242
if file := c.file.Swap(nil); file != nil {
281243
_ = file.Sync()
@@ -287,9 +249,9 @@ func (c *RotateFileAppender) Stop() {
287249
// If so, it closes the old file, opens a new one, and triggers cleanup.
288250
// Risk: If file creation fails during rotation, new logs will be lost
289251
// until the issue is resolved.
290-
func (c *RotateFileAppender) rotate() {
252+
func (c *FileAppender) rotate() {
291253
now := time.Now()
292-
nowTime := c.RotateStrategy.Time(now)
254+
nowTime := c.RollingPolicy.Time(now)
293255
if nowTime <= c.currTime.Load() {
294256
return // still in the current slot
295257
}
@@ -323,16 +285,16 @@ func (c *RotateFileAppender) rotate() {
323285
go c.clearExpiredFiles()
324286
}
325287

326-
func (c *RotateFileAppender) ConcurrentSafe() bool { return true }
288+
func (c *FileAppender) ConcurrentSafe() bool { return true }
327289

328-
func (c *RotateFileAppender) Append(e *Event) {
290+
func (c *FileAppender) Append(e *Event) {
329291
panic(util.ErrForbiddenMethod)
330292
}
331293

332294
// createFile creates or opens the current log file for appending.
333295
// The application is responsible for ensuring the directory exists.
334-
func (c *RotateFileAppender) createFile(t time.Time) (string, *os.File, error) {
335-
fileName := c.FileName + "." + c.RotateStrategy.Format(t)
296+
func (c *FileAppender) createFile(t time.Time) (string, *os.File, error) {
297+
fileName := c.FileName + "." + c.RollingPolicy.Format(t)
336298
filePath := filepath.Join(c.FileDir, fileName)
337299
const fileFlag = os.O_CREATE | os.O_WRONLY | os.O_APPEND
338300
file, err := os.OpenFile(filePath, fileFlag, 0644)
@@ -343,7 +305,7 @@ func (c *RotateFileAppender) createFile(t time.Time) (string, *os.File, error) {
343305
}
344306

345307
// clearExpiredFiles removes expired log files.
346-
func (c *RotateFileAppender) clearExpiredFiles() {
308+
func (c *FileAppender) clearExpiredFiles() {
347309
expiration := time.Now().Add(-time.Duration(c.ClearHours) * time.Hour)
348310
entries, _ := os.ReadDir(c.FileDir)
349311
for _, entry := range entries {

plugin_appender_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func TestFileAppender(t *testing.T) {
141141

142142
a.Stop()
143143

144-
b, err := os.ReadFile(a.file.Name())
144+
b, err := os.ReadFile(a.file.Load().Name())
145145
assert.Error(t, err).Nil()
146146
assert.String(t, string(b)).Equal("[INFO][0001-01-01T00:00:00.000][file.go:100] _def||msg=hello world\n")
147147
})

plugin_logger.go

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ type FileLogger struct {
253253
Separate bool `PluginAttribute:"separate,default=false"`
254254

255255
// rotation and cleanup configuration
256-
ClearHours int32 `PluginAttribute:"clearHours,default=168"`
257-
RotateStrategy RotateStrategy `PluginAttribute:"rotateStrategy,default=1h"`
256+
ClearHours int32 `PluginAttribute:"clearHours,default=168"`
257+
RollingPolicy RollingPolicy `PluginAttribute:"rollingPolicy,default=1h"`
258258

259259
// asynchronous logging configuration
260260
AsyncWrite bool `PluginAttribute:"async,default=false"`
@@ -267,7 +267,7 @@ type FileLogger struct {
267267
func (f *FileLogger) Start() error {
268268
if f.AsyncWrite {
269269
// Async mode: use AsyncLogger and AsyncRotateFileWriter
270-
return initFileLogger(f, NewSyncRotateFileWriter, func(f *FileLogger) Logger {
270+
return initFileLogger(f, func(f *FileLogger) Logger {
271271
return &AsyncLogger{
272272
LoggerBase: f.LoggerBase,
273273
BufferSize: f.BufferSize,
@@ -276,7 +276,7 @@ func (f *FileLogger) Start() error {
276276
})
277277
} else {
278278
// Sync mode: use SyncLogger and SyncRotateFileWriter
279-
return initFileLogger(f, NewSyncRotateFileWriter, func(f *FileLogger) Logger {
279+
return initFileLogger(f, func(f *FileLogger) Logger {
280280
return &SyncLogger{
281281
LoggerBase: f.LoggerBase,
282282
}
@@ -287,9 +287,8 @@ func (f *FileLogger) Start() error {
287287
// initFileLogger is a generic helper to configure both synchronous and asynchronous FileLogger.
288288
// - fnAppender creates either SyncRotateFileWriter or AsyncRotateFileWriter.
289289
// - fnLogger creates either SyncLogger or AsyncLogger.
290-
func initFileLogger[T FileWriter](
290+
func initFileLogger(
291291
f *FileLogger,
292-
fnAppender func(RotateFileWriterBase) T,
293292
fnLogger func(f *FileLogger) Logger,
294293
) error {
295294

@@ -303,35 +302,31 @@ func initFileLogger[T FileWriter](
303302
// Create appenders for the normal log file
304303
appenders := []*AppenderRef{
305304
{
306-
Appender: &FileWriterAsAppender{
305+
Appender: &FileAppender{
307306
AppenderBase: AppenderBase{
308307
MinLevel: f.MinLevel,
309308
MaxLevel: normalMaxLevel,
310309
},
311-
FileWriter: fnAppender(RotateFileWriterBase{
312-
FileDir: f.FileDir,
313-
FileName: f.FileName,
314-
ClearHours: f.ClearHours,
315-
RotateStrategy: f.RotateStrategy,
316-
}),
310+
FileDir: f.FileDir,
311+
FileName: f.FileName,
312+
ClearHours: f.ClearHours,
313+
RollingPolicy: f.RollingPolicy,
317314
},
318315
},
319316
}
320317

321318
// Create appenders for warning and error logs if Separate is enabled
322319
if f.Separate {
323320
appenders = append(appenders, &AppenderRef{
324-
Appender: &FileWriterAsAppender{
321+
Appender: &FileAppender{
325322
AppenderBase: AppenderBase{
326323
MinLevel: WarnLevel,
327324
MaxLevel: MaxLevel,
328325
},
329-
FileWriter: fnAppender(RotateFileWriterBase{
330-
FileDir: f.FileDir,
331-
FileName: f.FileName + ".wf",
332-
ClearHours: f.ClearHours,
333-
RotateStrategy: f.RotateStrategy,
334-
}),
326+
FileDir: f.FileDir,
327+
FileName: f.FileName + ".wf",
328+
ClearHours: f.ClearHours,
329+
RollingPolicy: f.RollingPolicy,
335330
},
336331
})
337332
}

0 commit comments

Comments
 (0)