diff --git a/define.go b/define.go index 334d2c0..3c038e3 100644 --- a/define.go +++ b/define.go @@ -2,7 +2,6 @@ package slog import ( "errors" - "io" "strings" ) @@ -57,50 +56,6 @@ func (ls Levels) Contains(level Level) bool { return false } -// FlushWriter is the interface satisfied by logging destinations. -type FlushWriter interface { - Flush() error - // Writer the output writer - io.Writer -} - -// FlushCloseWriter is the interface satisfied by logging destinations. -type FlushCloseWriter interface { - Flush() error - // WriteCloser the output writer - io.WriteCloser -} - -// FormatterWriterHandler interface -type FormatterWriterHandler interface { - Handler - // Formatter record formatter - Formatter() Formatter - // Writer the output writer - Writer() io.Writer -} - -// -// Handler interface -// - -// Handler interface definition -type Handler interface { - // Closer Close handler. - // You should first call Flush() on close logic. - // Refer the FileHandler.Close() handle - io.Closer - // Flush and sync logs to disk file. - Flush() error - // IsHandling Checks whether the given record will be handled by this handler. - IsHandling(level Level) bool - // Handle a log record. - // - // All records may be passed to this method, and the handler should discard - // those that it does not want to handle. - Handle(*Record) error -} - // // Processor interface // @@ -171,6 +126,12 @@ type FormattableHandler interface { SetFormatter(Formatter) } +// LevelFormattable support limit log levels and provide formatter +type LevelFormattable interface { + FormattableHandler + IsHandling(level Level) bool +} + // Formattable definition type Formattable struct { formatter Formatter diff --git a/handler.go b/handler.go new file mode 100644 index 0000000..808a14a --- /dev/null +++ b/handler.go @@ -0,0 +1,96 @@ +package slog + +import "io" + +// FlushWriter is the interface satisfied by logging destinations. +type FlushWriter interface { + Flush() error + // Writer the output writer + io.Writer +} + +// FlushCloseWriter is the interface satisfied by logging destinations. +type FlushCloseWriter interface { + Flush() error + // WriteCloser the output writer + io.WriteCloser +} + +// FormatterWriterHandler interface +type FormatterWriterHandler interface { + Handler + // Formatter record formatter + Formatter() Formatter + // Writer the output writer + Writer() io.Writer +} + +// +// Handler interface +// + +// Handler interface definition +type Handler interface { + // Closer Close handler. + // You should first call Flush() on close logic. + // Refer the FileHandler.Close() handle + io.Closer + // Flush and sync logs to disk file. + Flush() error + // IsHandling Checks whether the given record will be handled by this handler. + IsHandling(level Level) bool + // Handle a log record. + // + // All records may be passed to this method, and the handler should discard + // those that it does not want to handle. + Handle(*Record) error +} + +/******************************************************************************** + * Common parts for handler + ********************************************************************************/ + +// LevelWithFormatter struct definition +// +// - support set log formatter +// - only support set one log level +type LevelWithFormatter struct { + Formattable + // Level for log message. if current level <= Level will log message + Level Level +} + +// NewLvFormatter create new instance +func NewLvFormatter(lv Level) *LevelWithFormatter { + return &LevelWithFormatter{Level: lv} +} + +// IsHandling Check if the current level can be handling +func (h *LevelWithFormatter) IsHandling(level Level) bool { + return h.Level.ShouldHandling(level) +} + +// LevelsWithFormatter struct definition +// +// - support set log formatter +// - support setting multi log levels +type LevelsWithFormatter struct { + Formattable + // Levels for log message + Levels []Level +} + +// NewLvsFormatter create new instance +func NewLvsFormatter(levels []Level) *LevelsWithFormatter { + return &LevelsWithFormatter{Levels: levels} +} + +// IsHandling Check if the current level can be handling +func (h *LevelsWithFormatter) IsHandling(level Level) bool { + for _, l := range h.Levels { + if l == level { + return true + } + } + return false +} diff --git a/handler/base_common.go b/handler/base_common.go deleted file mode 100644 index ef6604f..0000000 --- a/handler/base_common.go +++ /dev/null @@ -1,57 +0,0 @@ -package handler - -import ( - "os" - "sync" - - "github.com/gookit/goutil/fsutil" -) - -// NopFlushClose no operation. -// -// provide empty Flush(), Close() methods, useful for tests. -type NopFlushClose struct{} - -// Flush logs to disk -func (h *NopFlushClose) Flush() error { - return nil -} - -// Close handler -func (h *NopFlushClose) Close() error { - return nil -} - -type lockWrapper struct { - sync.Mutex - disable bool -} - -// Lock it -func (lw *lockWrapper) Lock() { - if false == lw.disable { - lw.Mutex.Lock() - } -} - -// Unlock it -func (lw *lockWrapper) Unlock() { - if !lw.disable { - lw.Mutex.Unlock() - } -} - -// EnableLock enable lock -func (lw *lockWrapper) EnableLock(enable bool) { - lw.disable = false == enable -} - -// LockEnabled status -func (lw *lockWrapper) LockEnabled() bool { - return lw.disable == false -} - -// QuickOpenFile like os.OpenFile -func QuickOpenFile(filepath string) (*os.File, error) { - return fsutil.OpenFile(filepath, DefaultFileFlags, DefaultFilePerm) -} diff --git a/handler/buffer.go b/handler/buffer.go new file mode 100644 index 0000000..aa34cf0 --- /dev/null +++ b/handler/buffer.go @@ -0,0 +1,74 @@ +package handler + +import ( + "io" + "os" + + "github.com/gookit/slog" + "github.com/gookit/slog/bufwrite" +) + +// NewBuffered create new BufferedHandler +func NewBuffered(cWriter io.WriteCloser, bufSize int, levels ...slog.Level) *FlushCloseHandler { + return NewBufferedHandler(cWriter, bufSize, levels...) +} + +// NewBufferedHandler create new BufferedHandler +func NewBufferedHandler(cWriter io.WriteCloser, bufSize int, levels ...slog.Level) *FlushCloseHandler { + if len(levels) == 0 { + levels = slog.AllLevels + } + + return &FlushCloseHandler{ + Output: bufwrite.NewBufIOWriterSize(cWriter, bufSize), + // log levels + LevelFormattable: slog.NewLvsFormatter(levels), + } +} + +// LineBufferedFile handler +func LineBufferedFile(logfile string, bufSize int, levels []slog.Level) (slog.Handler, error) { + cfg := NewConfig( + WithLogfile(logfile), + WithBuffSize(bufSize), + WithLogLevels(levels), + WithBuffMode(BuffModeLine), + ) + + output, err := cfg.SyncCloseWriter() + if err != nil { + return nil, err + } + + return &SyncCloseHandler{ + Output: output, + // init log levels + LevelFormattable: slog.NewLvsFormatter(cfg.Levels), + }, nil +} + +// LineBuffOsFile handler +func LineBuffOsFile(f *os.File, bufSize int, levels []slog.Level) slog.Handler { + if f == nil { + panic("slog: the os file cannot be nil") + } + + return &SyncCloseHandler{ + Output: bufwrite.NewLineWriterSize(f, bufSize), + // init log levels + LevelFormattable: slog.NewLvsFormatter(levels), + } +} + +// LineBuffWriter handler +func LineBuffWriter(w io.Writer, bufSize int, levels []slog.Level) slog.Handler { + if w == nil { + panic("slog: the io writer cannot be nil") + } + + return &IOWriterHandler{ + Output: bufwrite.NewLineWriterSize(w, bufSize), + // init log levels + LevelFormattable: slog.NewLvsFormatter(levels), + } +} diff --git a/handler/buffer_lined.go b/handler/buffer_lined.go deleted file mode 100644 index 3b324c5..0000000 --- a/handler/buffer_lined.go +++ /dev/null @@ -1,49 +0,0 @@ -package handler - -import ( - "io" - "os" - - "github.com/gookit/slog" - "github.com/gookit/slog/bufwrite" -) - -// LineBufferedFile handler -func LineBufferedFile(fPath string, bufSize int, levels []slog.Level) slog.Handler { - f, err := QuickOpenFile(fPath) - if err != nil { - panic(err) - } - - return &IOWriterHandler{ - Output: bufwrite.NewLineWriterSize(f, bufSize), - // init log levels - LevelsWithFormatter: newLvsFormatter(levels), - } -} - -// LineBuffOsFile handler -func LineBuffOsFile(f *os.File, bufSize int, levels []slog.Level) slog.Handler { - if f == nil { - panic("slog: the os file cannot be nil") - } - - return &IOWriterHandler{ - Output: bufwrite.NewLineWriterSize(f, bufSize), - // init log levels - LevelsWithFormatter: newLvsFormatter(levels), - } -} - -// LineBuffWriter handler -func LineBuffWriter(w io.Writer, bufSize int, levels []slog.Level) slog.Handler { - if w == nil { - panic("slog: the io writer cannot be nil") - } - - return &IOWriterHandler{ - Output: bufwrite.NewLineWriterSize(w, bufSize), - // init log levels - LevelsWithFormatter: newLvsFormatter(levels), - } -} diff --git a/handler/buffered.go b/handler/buffered.go deleted file mode 100644 index 7ecac96..0000000 --- a/handler/buffered.go +++ /dev/null @@ -1,54 +0,0 @@ -package handler - -import ( - "bufio" - "io" - - "github.com/gookit/slog" -) - -// BufferedHandler definition -type BufferedHandler struct { - LevelsWithFormatter - buffer *bufio.Writer - writer io.WriteCloser -} - -// NewBuffered create new BufferedHandler -func NewBuffered(cWriter io.WriteCloser, bufSize int) *BufferedHandler { - return NewBufferedHandler(cWriter, bufSize) -} - -// NewBufferedHandler create new BufferedHandler -func NewBufferedHandler(cWriter io.WriteCloser, bufSize int) *BufferedHandler { - return &BufferedHandler{ - writer: cWriter, - buffer: bufio.NewWriterSize(cWriter, bufSize), - // log levels - LevelsWithFormatter: newLvsFormatter(slog.AllLevels), - } -} - -// Flush all buffers -func (h *BufferedHandler) Flush() error { - return h.buffer.Flush() -} - -// Close log records -func (h *BufferedHandler) Close() error { - if err := h.Flush(); err != nil { - return err - } - return h.writer.Close() -} - -// Handle log record -func (h *BufferedHandler) Handle(record *slog.Record) error { - bts, err := h.Formatter().Format(record) - if err != nil { - return err - } - - _, err = h.buffer.Write(bts) - return err -} diff --git a/handler/config.go b/handler/config.go index 39409f0..b9bece5 100644 --- a/handler/config.go +++ b/handler/config.go @@ -9,6 +9,11 @@ import ( "github.com/gookit/slog/rotatefile" ) +const ( + BuffModeLine = "line" + BuffModeBite = "bite" +) + // ConfigFn for config some settings type ConfigFn func(c *Config) @@ -18,6 +23,8 @@ type Config struct { Logfile string `json:"logfile" yaml:"logfile"` // UseJSON for format logs UseJSON bool `json:"use_json" yaml:"use_json"` + // BuffMode type. allow: line, bite + BuffMode string `json:"buff_mode" yaml:"buff_mode"` // BuffSize for enable buffer BuffSize int `json:"buff_size" yaml:"buff_size"` // Levels for log record @@ -30,15 +37,26 @@ type Config struct { RenameFunc func(filepath string, rotateNum uint) string } +// With more config settings func +func (c *Config) With(fns ...ConfigFn) *Config { + for _, fn := range fns { + fn(c) + } + return c +} + // SyncCloseWriter build by config func (c *Config) SyncCloseWriter() (output SyncCloseWriter, err error) { output, err = fsutil.QuickOpenFile(c.Logfile) // wrap buffer if c.BuffSize > 0 { - output = bufwrite.NewBufIOWriterSize(output, c.BuffSize) + if c.BuffMode == BuffModeLine { + output = bufwrite.NewLineWriterSize(output, c.BuffSize) + } else { + output = bufwrite.NewBufIOWriterSize(output, c.BuffSize) + } } - return } @@ -51,7 +69,11 @@ func (c *Config) RotateWriter() (output FlushCloseWriter, err error) { // wrap buffer if c.BuffSize > 0 { - output = bufwrite.NewBufIOWriterSize(output, c.BuffSize) + if c.BuffMode == BuffModeLine { + output = bufwrite.NewLineWriterSize(output, c.BuffSize) + } else { + output = bufwrite.NewBufIOWriterSize(output, c.BuffSize) + } } return } @@ -74,16 +96,14 @@ func (c *Config) RotateConfig() *rotatefile.Config { func NewConfig(fns ...ConfigFn) *Config { c := &Config{ MaxSize: rotatefile.DefaultMaxSize, + BuffMode: BuffModeLine, BuffSize: DefaultBufferSize, Levels: slog.NormalLevels, // time rotate settings RotateTime: rotatefile.EveryHour, } - for _, fn := range fns { - fn(c) - } - return c + return c.With(fns...) } // WithLogfile setting @@ -100,6 +120,13 @@ func WithRotateTime(rt rotatefile.RotateTime) ConfigFn { } } +// WithBuffMode setting +func WithBuffMode(buffMode string) ConfigFn { + return func(c *Config) { + c.BuffMode = buffMode + } +} + // WithBuffSize setting func WithBuffSize(buffSize int) ConfigFn { return func(c *Config) { diff --git a/handler/email.go b/handler/email.go index cbf9c46..8fe65f8 100644 --- a/handler/email.go +++ b/handler/email.go @@ -8,18 +8,16 @@ import ( // EmailOption struct type EmailOption struct { - SmtpHost string // eg "smtp.gmail.com" - SmtpPort string // eg "587" - FromAddr string // eg "yourEmail@gmail.com" - Password string + SmtpHost string `json:"smtp_host"` // eg "smtp.gmail.com" + SmtpPort string `json:"smtp_port"` // eg "587" + FromAddr string `json:"from_addr"` // eg "yourEmail@gmail.com" + Password string `json:"password"` } // EmailHandler struct type EmailHandler struct { - // NopFlushClose provide empty Flush(), Close() methods NopFlushClose - // LevelWithFormatter support level and formatter - LevelWithFormatter + slog.LevelWithFormatter // From the sender email information From EmailOption // ToAddresses list diff --git a/handler/example_test.go b/handler/example_test.go index df8627d..f73c83d 100644 --- a/handler/example_test.go +++ b/handler/example_test.go @@ -5,7 +5,7 @@ import ( "github.com/gookit/slog/handler" ) -func ExampleFileHandler() { +func Example_fileHandler() { withLevels := handler.WithLogLevels(slog.Levels{slog.PanicLevel, slog.ErrorLevel, slog.WarnLevel}) h1 := handler.MustFileHandler("/tmp/error.log", withLevels) @@ -20,10 +20,9 @@ func ExampleFileHandler() { slog.Error("error message") } -func ExampleRotateFileHandler() { - h1 := handler.MustRotateFile("/tmp/error.log", handler.EveryHour) - - h2 := handler.MustRotateFile("/tmp/info.log", handler.EveryHour) +func Example_rotateFileHandler() { + h1 := handler.MustRotateFile("/tmp/error.log", handler.EveryHour, handler.WithLogLevels(slog.DangerLevels)) + h2 := handler.MustRotateFile("/tmp/info.log", handler.EveryHour, handler.WithLogLevels(slog.NormalLevels)) slog.PushHandler(h1) slog.PushHandler(h2) diff --git a/handler/file.go b/handler/file.go index 8c8c765..dca59cc 100644 --- a/handler/file.go +++ b/handler/file.go @@ -1,27 +1,11 @@ package handler import ( - "io" - - "github.com/gookit/goutil/fsutil" "github.com/gookit/slog" - "github.com/gookit/slog/bufwrite" ) -// FileHandler definition -type FileHandler struct { - // LevelsWithFormatter support limit log levels and formatter - LevelsWithFormatter - output SyncCloseWriter -} - -// JSONFileHandler create new FileHandler with JSON formatter -func JSONFileHandler(logfile string) (*FileHandler, error) { - return NewFileHandler(logfile, WithUseJSON(true)) -} - // MustFileHandler create file handler -func MustFileHandler(logfile string, fns ...ConfigFn) *FileHandler { +func MustFileHandler(logfile string, fns ...ConfigFn) *SyncCloseHandler { h, err := NewFileHandler(logfile, fns...) if err != nil { panic(err) @@ -29,73 +13,37 @@ func MustFileHandler(logfile string, fns ...ConfigFn) *FileHandler { return h } +// JSONFileHandler create new FileHandler with JSON formatter +func JSONFileHandler(logfile string, fns ...ConfigFn) (*SyncCloseHandler, error) { + fns = append(fns, WithUseJSON(true)) + + return NewFileHandler(logfile, fns...) +} + // NewBuffFileHandler create file handler with buff size -func NewBuffFileHandler(filePath string, buffSize int, fns ...ConfigFn) (*FileHandler, error) { +func NewBuffFileHandler(logfile string, buffSize int, fns ...ConfigFn) (*SyncCloseHandler, error) { fns = append(fns, WithBuffSize(buffSize)) - return NewFileHandler(filePath, fns...) + return NewFileHandler(logfile, fns...) } // NewFileHandler create new FileHandler -func NewFileHandler(logfile string, fns ...ConfigFn) (h *FileHandler, err error) { - cfg := NewConfig(fns...) - cfg.Logfile = logfile +func NewFileHandler(logfile string, fns ...ConfigFn) (h *SyncCloseHandler, err error) { + cfg := NewConfig(fns...).With(WithLogfile(logfile)) - var output SyncCloseWriter - output, err = fsutil.QuickOpenFile(logfile) + output, err := cfg.SyncCloseWriter() if err != nil { return nil, err } - // wrap buffer - if cfg.BuffSize > 0 { - output = bufwrite.NewBufIOWriterSize(output, cfg.BuffSize) - } - - h = &FileHandler{ - output: output, + h = &SyncCloseHandler{ + Output: output, // with log levels and formatter - LevelsWithFormatter: newLvsFormatter(cfg.Levels), + LevelFormattable: slog.NewLvsFormatter(cfg.Levels), } if cfg.UseJSON { h.SetFormatter(slog.NewJSONFormatter()) } - return h, nil } - -// Writer return output writer -func (h *FileHandler) Writer() io.Writer { - return h.output -} - -// Close handler, will be flush logs to file, then close file -func (h *FileHandler) Close() error { - if err := h.Flush(); err != nil { - return err - } - - return h.output.Close() -} - -// Flush logs to disk file -func (h *FileHandler) Flush() error { - return h.output.Sync() -} - -// Handle the log record -func (h *FileHandler) Handle(r *slog.Record) (err error) { - var bts []byte - bts, err = h.Formatter().Format(r) - if err != nil { - return - } - - // if enable lock - // h.Lock() - // defer h.Unlock() - - _, err = h.output.Write(bts) - return -} diff --git a/handler/file_test.go b/handler/file_test.go index b1e9cee..d20cc18 100644 --- a/handler/file_test.go +++ b/handler/file_test.go @@ -16,7 +16,7 @@ const testSubFile = "./testdata/subdir/app.log" func TestNewFileHandler(t *testing.T) { assert.NoError(t, fsutil.DeleteIfFileExist(testFile)) - h, err := handler.NewFileHandler(testFile, false) + h, err := handler.NewFileHandler(testFile) assert.NoError(t, err) l := slog.NewWithHandlers(h) diff --git a/handler/handler.go b/handler/handler.go index 1fbd2d6..14d53b3 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -6,7 +6,9 @@ package handler import ( "io" "os" + "sync" + "github.com/gookit/goutil/fsutil" "github.com/gookit/slog" ) @@ -52,17 +54,14 @@ type SyncCloseWriter interface { // // - support set log formatter // - only support set one log level +// +// Deprecated: please use slog.LevelWithFormatter instead. type LevelWithFormatter struct { slog.Formattable // Level for log message. if current level <= Level will log message Level slog.Level } -// create new instance -func newLvFormatter(lv slog.Level) LevelWithFormatter { - return LevelWithFormatter{Level: lv} -} - // IsHandling Check if the current level can be handling func (h *LevelWithFormatter) IsHandling(level slog.Level) bool { return h.Level.ShouldHandling(level) @@ -72,17 +71,14 @@ func (h *LevelWithFormatter) IsHandling(level slog.Level) bool { // // - support set log formatter // - support setting multi log levels +// +// Deprecated: please use slog.LevelsWithFormatter instead. type LevelsWithFormatter struct { slog.Formattable // Levels for log message Levels []slog.Level } -// create new instance -func newLvsFormatter(lvs []slog.Level) LevelsWithFormatter { - return LevelsWithFormatter{Levels: lvs} -} - // IsHandling Check if the current level can be handling func (h *LevelsWithFormatter) IsHandling(level slog.Level) bool { for _, l := range h.Levels { @@ -92,3 +88,53 @@ func (h *LevelsWithFormatter) IsHandling(level slog.Level) bool { } return false } + +// NopFlushClose no operation. +// +// provide empty Flush(), Close() methods, useful for tests. +type NopFlushClose struct{} + +// Flush logs to disk +func (h *NopFlushClose) Flush() error { + return nil +} + +// Close handler +func (h *NopFlushClose) Close() error { + return nil +} + +// LockWrapper struct +type LockWrapper struct { + sync.Mutex + disable bool +} + +// Lock it +func (lw *LockWrapper) Lock() { + if false == lw.disable { + lw.Mutex.Lock() + } +} + +// Unlock it +func (lw *LockWrapper) Unlock() { + if !lw.disable { + lw.Mutex.Unlock() + } +} + +// EnableLock enable lock +func (lw *LockWrapper) EnableLock(enable bool) { + lw.disable = false == enable +} + +// LockEnabled status +func (lw *LockWrapper) LockEnabled() bool { + return lw.disable == false +} + +// QuickOpenFile like os.OpenFile +func QuickOpenFile(filepath string) (*os.File, error) { + return fsutil.OpenFile(filepath, DefaultFileFlags, DefaultFilePerm) +} diff --git a/handler/multi_file.go b/handler/multi_file.go index ba31037..5a1ca27 100644 --- a/handler/multi_file.go +++ b/handler/multi_file.go @@ -8,7 +8,7 @@ import ( // MultiFileHandler definition type MultiFileHandler struct { - lockWrapper + LockWrapper writers map[string]io.Writer // FileDir for save log files FileDir string @@ -48,6 +48,6 @@ func (h *MultiFileHandler) Flush() error { panic("implement me") } -func (h *MultiFileHandler) Handle(record *slog.Record) error { +func (h *MultiFileHandler) Handle(_ *slog.Record) error { panic("implement me") } diff --git a/handler/rotate_file.go b/handler/rotate_file.go index 19940ac..37f299b 100644 --- a/handler/rotate_file.go +++ b/handler/rotate_file.go @@ -8,14 +8,14 @@ import ( // RotateFileHandler struct definition // It also supports splitting log files by time and size type RotateFileHandler struct { - // lockWrapper - LevelsWithFormatter + // LockWrapper + slog.LevelFormattable output FlushCloseWriter } // MustRotateFile instance func MustRotateFile(logfile string, rt rotatefile.RotateTime, fns ...ConfigFn) *RotateFileHandler { - h, err := NewRotateFileHandler(logfile, rt) + h, err := NewRotateFileHandler(logfile, rt, fns...) if err != nil { panic(err) } @@ -24,14 +24,12 @@ func MustRotateFile(logfile string, rt rotatefile.RotateTime, fns ...ConfigFn) * // NewRotateFile instance func NewRotateFile(logfile string, rt rotatefile.RotateTime, fns ...ConfigFn) (*RotateFileHandler, error) { - return NewRotateFileHandler(logfile, rt) + return NewRotateFileHandler(logfile, rt, fns...) } // NewRotateFileHandler instance func NewRotateFileHandler(logfile string, rt rotatefile.RotateTime, fns ...ConfigFn) (*RotateFileHandler, error) { - cfg := NewConfig(fns...) - cfg.Logfile = logfile - cfg.RotateTime = rt + cfg := NewConfig(fns...).With(WithLogfile(logfile), WithRotateTime(rt)) writer, err := cfg.RotateWriter() if err != nil { @@ -41,7 +39,7 @@ func NewRotateFileHandler(logfile string, rt rotatefile.RotateTime, fns ...Confi h := &RotateFileHandler{ output: writer, // with log levels and formatter - LevelsWithFormatter: newLvsFormatter(cfg.Levels), + LevelFormattable: slog.NewLvsFormatter(cfg.Levels), } return h, nil diff --git a/handler/simple.go b/handler/simple.go index 88b7e44..0de9e03 100644 --- a/handler/simple.go +++ b/handler/simple.go @@ -8,7 +8,7 @@ import ( // SimpleHandler definition type SimpleHandler struct { - LevelWithFormatter + slog.LevelFormattable Output io.Writer } @@ -34,7 +34,7 @@ func NewSimpleHandler(out io.Writer, level slog.Level) *SimpleHandler { return &SimpleHandler{ Output: out, // init log levels - LevelWithFormatter: newLvFormatter(level), + LevelFormattable: slog.NewLvFormatter(level), } } diff --git a/handler/simple_file.go b/handler/simple_file.go index 78c1539..8705b6a 100644 --- a/handler/simple_file.go +++ b/handler/simple_file.go @@ -5,15 +5,8 @@ import ( "github.com/gookit/slog" ) -// SimpleFileHandler struct -// - no buffer, will direct write logs to file. -type SimpleFileHandler struct { - out SyncCloseWrapper - LevelWithFormatter -} - // MustSimpleFile new instance -func MustSimpleFile(filepath string) *SimpleFileHandler { +func MustSimpleFile(filepath string) *SyncCloseHandler { h, err := NewSimpleFileHandler(filepath) if err != nil { panic(err) @@ -23,7 +16,7 @@ func MustSimpleFile(filepath string) *SimpleFileHandler { } // NewSimpleFile new instance -func NewSimpleFile(filepath string) (*SimpleFileHandler, error) { +func NewSimpleFile(filepath string) (*SyncCloseHandler, error) { return NewSimpleFileHandler(filepath) } @@ -36,30 +29,17 @@ func NewSimpleFile(filepath string) (*SimpleFileHandler, error) { // h.SetFormatter(slog.NewJSONFormatter()) // slog.PushHandler(h) // slog.Info("log message") -func NewSimpleFileHandler(filePath string) (*SimpleFileHandler, error) { +func NewSimpleFileHandler(filePath string) (*SyncCloseHandler, error) { file, err := fsutil.QuickOpenFile(filePath) if err != nil { return nil, err } - h := &SimpleFileHandler{ - out: NewSyncCloseWrapper(file), + h := &SyncCloseHandler{ + Output: file, // init default log level - LevelWithFormatter: newLvFormatter(slog.InfoLevel), + LevelFormattable: slog.NewLvFormatter(slog.InfoLevel), } return h, nil } - -// Handle the log record -func (h *SimpleFileHandler) Handle(r *slog.Record) (err error) { - var bts []byte - bts, err = h.Formatter().Format(r) - if err != nil { - return - } - - // direct write logs - _, err = h.out.Write(bts) - return -} diff --git a/handler/syslog.go b/handler/syslog.go index dafbe6e..4e41fda 100644 --- a/handler/syslog.go +++ b/handler/syslog.go @@ -1,3 +1,4 @@ +//go:build !windows && !nacl && !plan9 // +build !windows,!nacl,!plan9 package handler @@ -10,8 +11,8 @@ import ( // SysLogHandler struct type SysLogHandler struct { - slWriter *syslog.Writer - LevelWithFormatter + slog.LevelWithFormatter + writer *syslog.Writer } // NewSysLogHandler instance @@ -22,7 +23,7 @@ func NewSysLogHandler(priority syslog.Priority, tag string) (*SysLogHandler, err } h := &SysLogHandler{ - slWriter: slWriter, + writer: slWriter, } // init default log level @@ -30,20 +31,22 @@ func NewSysLogHandler(priority syslog.Priority, tag string) (*SysLogHandler, err return h, nil } -// Handle an record +// Handle a log record func (h *SysLogHandler) Handle(record *slog.Record) error { bts, err := h.Formatter().Format(record) if err != nil { return err } - return h.slWriter.Info(string(bts)) + return h.writer.Info(string(bts)) } +// Close handler func (h *SysLogHandler) Close() error { - return h.slWriter.Close() + return h.writer.Close() } +// Flush handler func (h *SysLogHandler) Flush() error { return nil } diff --git a/handler/write_close_flusher.go b/handler/write_close_flusher.go index b9081bc..2d46e0c 100644 --- a/handler/write_close_flusher.go +++ b/handler/write_close_flusher.go @@ -6,7 +6,7 @@ import ( // FlushCloseHandler definition type FlushCloseHandler struct { - LevelsWithFormatter + slog.LevelFormattable Output FlushCloseWriter } @@ -27,7 +27,7 @@ func NewFlushCloseHandler(out FlushCloseWriter, levels []slog.Level) *FlushClose return &FlushCloseHandler{ Output: out, // init log levels - LevelsWithFormatter: newLvsFormatter(levels), + LevelFormattable: slog.NewLvsFormatter(levels), } } diff --git a/handler/write_close_syncer.go b/handler/write_close_syncer.go index 2d4d4a4..6694028 100644 --- a/handler/write_close_syncer.go +++ b/handler/write_close_syncer.go @@ -4,40 +4,9 @@ import ( "github.com/gookit/slog" ) -// SyncCloseWrapper definition -type SyncCloseWrapper struct { - Output SyncCloseWriter -} - -// NewSyncCloseWrapper instance -func NewSyncCloseWrapper(out SyncCloseWriter) SyncCloseWrapper { - return SyncCloseWrapper{ - Output: out, - } -} - -// Close the handler -func (w *SyncCloseWrapper) Close() error { - if err := w.Flush(); err != nil { - return err - } - return w.Output.Close() -} - -// Flush the handler -func (w *SyncCloseWrapper) Flush() error { - return w.Output.Sync() -} - -// Write the handler -func (w *SyncCloseWrapper) Write(p []byte) (int, error) { - return w.Output.Write(p) -} - // SyncCloseHandler definition type SyncCloseHandler struct { - // lockWrapper - LevelsWithFormatter + slog.LevelFormattable Output SyncCloseWriter } @@ -58,7 +27,7 @@ func NewSyncCloseHandler(out SyncCloseWriter, levels []slog.Level) *SyncCloseHan return &SyncCloseHandler{ Output: out, // init log levels - LevelsWithFormatter: newLvsFormatter(levels), + LevelFormattable: slog.NewLvsFormatter(levels), } } @@ -88,3 +57,33 @@ func (h *SyncCloseHandler) Handle(record *slog.Record) error { _, err = h.Output.Write(bts) return err } + +// SyncCloseWrapper definition +type SyncCloseWrapper struct { + Output SyncCloseWriter +} + +// NewSyncCloseWrapper instance +func NewSyncCloseWrapper(out SyncCloseWriter) SyncCloseWrapper { + return SyncCloseWrapper{ + Output: out, + } +} + +// Close the handler +func (w *SyncCloseWrapper) Close() error { + if err := w.Flush(); err != nil { + return err + } + return w.Output.Close() +} + +// Flush the handler +func (w *SyncCloseWrapper) Flush() error { + return w.Output.Sync() +} + +// Write the handler +func (w *SyncCloseWrapper) Write(p []byte) (int, error) { + return w.Output.Write(p) +} diff --git a/handler/write_closer.go b/handler/write_closer.go index 6428cd2..26acfa9 100644 --- a/handler/write_closer.go +++ b/handler/write_closer.go @@ -8,8 +8,8 @@ import ( // WriteCloserHandler definition type WriteCloserHandler struct { - // lockWrapper - LevelsWithFormatter + // LockWrapper + slog.LevelFormattable Output io.WriteCloser } @@ -30,7 +30,7 @@ func NewIOWriteCloserHandler(out io.WriteCloser, levels []slog.Level) *WriteClos return &WriteCloserHandler{ Output: out, // init log levels - LevelsWithFormatter: newLvsFormatter(levels), + LevelFormattable: slog.NewLvsFormatter(levels), } } diff --git a/handler/writer.go b/handler/writer.go index 0b6a92a..6d972b0 100644 --- a/handler/writer.go +++ b/handler/writer.go @@ -8,7 +8,7 @@ import ( // IOWriterHandler definition type IOWriterHandler struct { - LevelsWithFormatter + slog.LevelFormattable Output io.Writer } @@ -29,7 +29,7 @@ func NewIOWriterHandler(out io.Writer, levels []slog.Level) *IOWriterHandler { return &IOWriterHandler{ Output: out, // init log levels - LevelsWithFormatter: newLvsFormatter(levels), + LevelFormattable: slog.NewLvsFormatter(levels), } } diff --git a/logger_test.go b/logger_test.go index 8c0cdc6..1dcee11 100644 --- a/logger_test.go +++ b/logger_test.go @@ -25,7 +25,7 @@ func TestLogger_AddHandlers(t *testing.T) { } type bufferHandler struct { - handler.LevelsWithFormatter + slog.LevelsWithFormatter } func (h *bufferHandler) Handle(_ *slog.Record) error {