-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathconfig.go
320 lines (258 loc) · 8.01 KB
/
config.go
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
package handler
import (
"io"
"io/fs"
"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 write 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
Level slog.Level `json:"level" yaml:"level"`
// Levels list for write. 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
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 rotate file, unit is seconds.
RotateTime rotatefile.RotateTime `json:"rotate_time" yaml:"rotate_time"`
// RotateMode for rotate file by time. default rotatefile.ModeRename
RotateMode rotatefile.RotateMode `json:"rotate_mode" yaml:"rotate_mode"`
// TimeClock for rotate file by time.
TimeClock rotatefile.Clocker `json:"-" yaml:"-"`
// MaxSize on rotate 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
// 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,
}
return c.WithConfigFn(fns...)
}
// 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
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(mode slog.LevelMode) ConfigFn {
return func(c *Config) { c.LevelMode = mode }
}
// WithLogLevel setting
func WithLogLevel(level slog.Level) ConfigFn {
return func(c *Config) { c.Level = level }
}
// WithLogLevels setting
func WithLogLevels(levels slog.Levels) ConfigFn {
return func(c *Config) { c.Levels = levels }
}
// WithLevelNames set 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 func(c *Config) {
c.Levels = levels
}
}
// WithRotateTime setting rotate time
func WithRotateTime(rt rotatefile.RotateTime) ConfigFn {
return func(c *Config) { c.RotateTime = rt }
}
// WithRotateMode setting rotate mode
func WithRotateMode(m rotatefile.RotateMode) ConfigFn {
return func(c *Config) { 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
func WithBuffSize(buffSize int) ConfigFn {
return func(c *Config) { c.BuffSize = buffSize }
}
// WithMaxSize setting max size for rotate 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 use 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 }