package logging import ( "errors" "fmt" "io" "os" ) type Backend interface { Write(*Record) error SetFormatter(*Formatter) SetLevel(Level) Level() Level Reopen() error } // // Backend to write in file-like objects // type FileBackend struct { l io.Writer formatter *Formatter level Level filepath string } // Creates a new backend to write the logs on the standard output func NewStdoutBackend() (b *FileBackend) { b = &FileBackend{ l: os.Stdout, formatter: &defaultFormatter, } return } // Creates a new backend to write the logs on the error output func NewStderrBackend() (b *FileBackend) { b = &FileBackend{ l: os.Stderr, formatter: &defaultFormatter, } return } // Creates a new backend to write the logs in a given file func NewFileBackend(filename string) (b *FileBackend, e error) { filename_fd, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) if err != nil { e = errors.New(fmt.Sprintf("Cannot open log file %s (%s)", filename, err.Error())) } b = &FileBackend{ l: filename_fd, formatter: &defaultFormatter, filepath: filename, } return } // Creates a new backend to write the logs in a given io.Writer func NewIoBackend(buf io.Writer) (b *FileBackend) { return &FileBackend{ l: buf, formatter: &defaultFormatter, } } func (b FileBackend) Write(r *Record) error { text := (*b.formatter)(r) _, err := io.WriteString(b.l, text) return err } func (b *FileBackend) SetLevel(l Level) { b.level = l } func (b *FileBackend) Level() Level { return b.level } func (b *FileBackend) SetFormatter(f *Formatter) { b.formatter = f } func (b *FileBackend) Reopen() error { if b.filepath == "" { return nil } if c, ok := b.l.(io.Closer); ok { if err := c.Close(); err != nil { return err } } fd, err := os.OpenFile(b.filepath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) if err != nil { return fmt.Errorf("Cannot open log file %s: %w", b.filepath, err) } b.l = fd return nil } // // Noop Backend // type NoopBackend struct{} func NewNoopBackend() (Backend, error) { return &NoopBackend{}, nil } func (nb *NoopBackend) Write(r *Record) error { return nil } func (nb *NoopBackend) SetFormatter(f *Formatter) {} func (nb *NoopBackend) SetLevel(level Level) {} func (nb *NoopBackend) Level() Level { return DefaultLevel } func (nb *NoopBackend) Reopen() error { return nil }