-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathconfig.go
More file actions
375 lines (306 loc) · 9.76 KB
/
config.go
File metadata and controls
375 lines (306 loc) · 9.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
package handler
import (
"encoding/json"
"io"
"io/fs"
"strings"
"github.com/gookit/goutil/errorx"
"github.com/gookit/goutil/fsutil"
"github.com/gookit/slog"
"github.com/gookit/slog/bufwrite"
"github.com/gookit/slog/rotatefile"
)
// the buff mode constants
const (
BuffModeLine = "line"
BuffModeBite = "bite"
)
const (
// LevelModeList use level list for limit record write
LevelModeList = slog.LevelModeList
// LevelModeValue use max level limit log record write
LevelModeValue = slog.LevelModeMax
)
// ConfigFn for config some settings
type ConfigFn func(c *Config)
// Config struct
type Config struct {
// Logfile for writing logs
Logfile string `json:"logfile" yaml:"logfile"`
// FilePerm for create log file. default rotatefile.DefaultFilePerm
FilePerm fs.FileMode `json:"file_perm" yaml:"file_perm"`
// LevelMode for limit log records. default LevelModeList
LevelMode slog.LevelMode `json:"level_mode" yaml:"level_mode"`
// Level max value. valid on LevelMode = LevelModeValue
//
// eg: set Level=slog.LevelError, it will only write messages on level <= error.
Level slog.Level `json:"level" yaml:"level"`
// Levels list for writing. valid on LevelMode = LevelModeList
Levels []slog.Level `json:"levels" yaml:"levels"`
// UseJSON for format logs
UseJSON bool `json:"use_json" yaml:"use_json"`
// BuffMode type name. allow: line, bite
//
// Recommend use BuffModeLine(it's default)
BuffMode string `json:"buff_mode" yaml:"buff_mode"`
// BuffSize for enable buffer, unit is bytes. set 0 to disable buffer
BuffSize int `json:"buff_size" yaml:"buff_size"`
// RotateTime for a rotating file, unit is seconds.
RotateTime rotatefile.RotateTime `json:"rotate_time" yaml:"rotate_time"`
// RotateMode for a rotating file by time. default rotatefile.ModeRename
RotateMode rotatefile.RotateMode `json:"rotate_mode" yaml:"rotate_mode"`
// TimeClock for a rotating file by time.
TimeClock rotatefile.Clocker `json:"-" yaml:"-"`
// MaxSize for a rotating file by size, unit is bytes.
MaxSize uint64 `json:"max_size" yaml:"max_size"`
// 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"`
// BackupNum max number for keep old files.
//
// 0 is not limit, default is 20.
BackupNum uint `json:"backup_num" yaml:"backup_num"`
// BackupTime max time for keep old files, unit is hours.
//
// 0 is not limit, default is a week.
BackupTime uint `json:"backup_time" yaml:"backup_time"`
// RenameFunc build filename for rotate file
RenameFunc func(filepath string, rotateNum uint) string
// CleanOnClose determines if the rotated log files should be cleaned up when close.
CleanOnClose bool `json:"clean_on_close" yaml:"clean_on_close"`
// DebugMode for debug on development.
DebugMode bool
}
// NewEmptyConfig new config instance
func NewEmptyConfig(fns ...ConfigFn) *Config {
c := &Config{Levels: slog.AllLevels}
return c.WithConfigFn(fns...)
}
// NewConfig new config instance with some default settings.
func NewConfig(fns ...ConfigFn) *Config {
c := &Config{
Levels: slog.AllLevels,
BuffMode: BuffModeLine,
BuffSize: DefaultBufferSize,
// rotate file settings
MaxSize: rotatefile.DefaultMaxSize,
RotateTime: rotatefile.EveryHour,
// old files clean settings
BackupNum: rotatefile.DefaultBackNum,
BackupTime: rotatefile.DefaultBackTime,
DebugMode: slog.DebugMode,
}
return c.WithConfigFn(fns...)
}
// FromJSON load config from json string
func (c *Config) FromJSON(bts []byte) error { return json.Unmarshal(bts, c) }
// With more config settings func
func (c *Config) With(fns ...ConfigFn) *Config { return c.WithConfigFn(fns...) }
// WithConfigFn more config settings func
func (c *Config) WithConfigFn(fns ...ConfigFn) *Config {
for _, fn := range fns {
fn(c)
}
return c
}
func (c *Config) newLevelFormattable() slog.LevelFormattable {
if c.LevelMode == LevelModeValue {
return slog.NewLvFormatter(c.Level)
}
return slog.NewLvsFormatter(c.Levels)
}
// CreateHandler quick create a handler by config
func (c *Config) CreateHandler() (*SyncCloseHandler, error) {
output, err := c.CreateWriter()
if err != nil {
return nil, err
}
h := &SyncCloseHandler{
Output: output,
// with log level and formatter
LevelFormattable: c.newLevelFormattable(),
}
if c.UseJSON {
h.SetFormatter(slog.NewJSONFormatter())
}
return h, nil
}
// RotateWriter build rotate writer by config
func (c *Config) RotateWriter() (output SyncCloseWriter, err error) {
if c.MaxSize == 0 && c.RotateTime == 0 {
return nil, errorx.E("slog: cannot create rotate writer, MaxSize and RotateTime both is 0")
}
return c.CreateWriter()
}
// CreateWriter build writer by config
func (c *Config) CreateWriter() (output SyncCloseWriter, err error) {
if c.Logfile == "" {
return nil, errorx.Raw("slog: logfile cannot be empty for create writer")
}
if c.FilePerm == 0 {
c.FilePerm = rotatefile.DefaultFilePerm
}
// create a rotated writer by config.
if c.MaxSize > 0 || c.RotateTime > 0 {
rc := rotatefile.EmptyConfigWith()
// has locked on logger.write()
rc.CloseLock = true
rc.Filepath = c.Logfile
rc.FilePerm = c.FilePerm
rc.DebugMode = c.DebugMode
// copy settings
rc.MaxSize = c.MaxSize
rc.RotateTime = c.RotateTime
rc.RotateMode = c.RotateMode
rc.BackupNum = c.BackupNum
rc.BackupTime = c.BackupTime
rc.Compress = c.Compress
rc.CleanOnClose = c.CleanOnClose
if c.RenameFunc != nil {
rc.RenameFunc = c.RenameFunc
}
if c.TimeClock != nil {
rc.TimeClock = c.TimeClock
}
output, err = rc.Create()
} else {
// create a file writer
output, err = fsutil.OpenAppendFile(c.Logfile, c.FilePerm)
}
if err != nil {
return nil, err
}
// wrap buffer
if c.BuffSize > 0 {
output = c.wrapBuffer(output)
}
return
}
type flushSyncCloseWriter interface {
FlushCloseWriter
Sync() error
}
// wrap buffer for the writer
func (c *Config) wrapBuffer(w io.Writer) (bw flushSyncCloseWriter) {
if c.BuffMode == BuffModeLine {
bw = bufwrite.NewLineWriterSize(w, c.BuffSize)
} else {
bw = bufwrite.NewBufIOWriterSize(w, c.BuffSize)
}
return bw
}
//
// ---------------------------------------------------------------------------
// global config func
// ---------------------------------------------------------------------------
//
// WithLogfile setting
func WithLogfile(logfile string) ConfigFn {
return func(c *Config) { c.Logfile = logfile }
}
// WithFilePerm setting
func WithFilePerm(filePerm fs.FileMode) ConfigFn {
return func(c *Config) { c.FilePerm = filePerm }
}
// WithLevelMode setting
func WithLevelMode(lm slog.LevelMode) ConfigFn {
return func(c *Config) { c.LevelMode = lm }
}
// WithLevelModeString setting
func WithLevelModeString(s string) ConfigFn {
return func(c *Config) { c.LevelMode = slog.SafeToLevelMode(s) }
}
// WithLogLevel setting max log level
func WithLogLevel(level slog.Level) ConfigFn {
return func(c *Config) {
c.Level = level
c.LevelMode = LevelModeValue
}
}
// WithLevelName setting max level by name
func WithLevelName(name string) ConfigFn { return WithLogLevel(slog.LevelByName(name)) }
// WithMaxLevelName setting max level by name
func WithMaxLevelName(name string) ConfigFn { return WithLogLevel(slog.LevelByName(name)) }
// WithLogLevels setting
func WithLogLevels(levels slog.Levels) ConfigFn {
return func(c *Config) {
c.Levels = levels
c.LevelMode = LevelModeList
}
}
// WithLevelNamesString setting multi levels by level names string, multi names split by comma.
func WithLevelNamesString(names string) ConfigFn {
return WithLevelNames(strings.Split(names, ","))
}
// WithLevelNames set multi levels by level names.
func WithLevelNames(names []string) ConfigFn {
levels := make([]slog.Level, 0, len(names))
for _, name := range names {
levels = append(levels, slog.LevelByName(name))
}
return WithLogLevels(levels)
}
// WithRotateTime setting the rotated time
func WithRotateTime(rt rotatefile.RotateTime) ConfigFn {
return func(c *Config) { c.RotateTime = rt }
}
// WithRotateTimeString setting the rotated time by string.
//
// eg: "1hour", "24h", "1day", "7d", "1m", "30s"
func WithRotateTimeString(s string) ConfigFn {
return func(c *Config) {
rt, err := rotatefile.StringToRotateTime(s)
if err != nil {
panic(err)
}
c.RotateTime = rt
}
}
// WithRotateMode setting rotating mode rotatefile.RotateMode
func WithRotateMode(m rotatefile.RotateMode) ConfigFn {
return func(c *Config) { c.RotateMode = m }
}
// WithRotateModeString setting rotatefile.RotateMode by string.
func WithRotateModeString(s string) ConfigFn {
return func(c *Config) {
m, err := rotatefile.StringToRotateMode(s)
if err != nil {
panic(err)
}
c.RotateMode = m
}
}
// WithTimeClock setting
func WithTimeClock(clock rotatefile.Clocker) ConfigFn {
return func(c *Config) { c.TimeClock = clock }
}
// WithBackupNum setting
func WithBackupNum(n uint) ConfigFn {
return func(c *Config) { c.BackupNum = n }
}
// WithBackupTime setting backup time
func WithBackupTime(bt uint) ConfigFn {
return func(c *Config) { c.BackupTime = bt }
}
// WithBuffMode setting buffer mode
func WithBuffMode(buffMode string) ConfigFn {
return func(c *Config) { c.BuffMode = buffMode }
}
// WithBuffSize setting buffer size, unit is bytes.
func WithBuffSize(buffSize int) ConfigFn {
return func(c *Config) { c.BuffSize = buffSize }
}
// WithMaxSize setting max size for a rotated file
func WithMaxSize(maxSize uint64) ConfigFn {
return func(c *Config) { c.MaxSize = maxSize }
}
// WithCompress setting compress
func WithCompress(compress bool) ConfigFn {
return func(c *Config) { c.Compress = compress }
}
// WithUseJSON setting uses JSON format
func WithUseJSON(useJSON bool) ConfigFn {
return func(c *Config) { c.UseJSON = useJSON }
}
// WithDebugMode setting for debug mode
func WithDebugMode(c *Config) { c.DebugMode = true }