173 lines
3.5 KiB
Go
173 lines
3.5 KiB
Go
package logging
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// Backend is the interface that specifies the methods that a backend must
|
|
// implement.
|
|
type Backend interface {
|
|
Write(*Record) error
|
|
SetFormatter(Formatter)
|
|
SetLevel(Level)
|
|
Level() Level
|
|
Reopen() error
|
|
Close() error
|
|
}
|
|
|
|
//
|
|
// Backend to write in file-like objects
|
|
//
|
|
|
|
var _ Backend = &FileBackend{}
|
|
|
|
// FileBackend is a backend that writes to a file.
|
|
type FileBackend struct {
|
|
formatter Formatter
|
|
l io.Writer
|
|
filepath string
|
|
level Level
|
|
}
|
|
|
|
// NewStdoutBackend creates a new backend to write the logs on the standard
|
|
// output.
|
|
func NewStdoutBackend() *FileBackend {
|
|
return &FileBackend{
|
|
l: os.Stdout,
|
|
formatter: defaultFormatter,
|
|
}
|
|
}
|
|
|
|
// NewStderrBackend creates a new backend to write the logs on the error output.
|
|
func NewStderrBackend() *FileBackend {
|
|
return &FileBackend{
|
|
l: os.Stderr,
|
|
formatter: defaultFormatter,
|
|
}
|
|
}
|
|
|
|
// NewFileBackend creates a new backend to write the logs in a given file.
|
|
func NewFileBackend(filename string) (*FileBackend, error) {
|
|
fd, err := os.OpenFile(filepath.Clean(filename),
|
|
os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o600)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot open log file %s: %w", filename, err)
|
|
}
|
|
|
|
b := &FileBackend{
|
|
l: fd,
|
|
formatter: defaultFormatter,
|
|
filepath: filename,
|
|
}
|
|
|
|
return b, nil
|
|
}
|
|
|
|
// NewIoBackend creates a new backend to write the logs in a given io.Writer.
|
|
func NewIoBackend(buf io.Writer) *FileBackend {
|
|
return &FileBackend{
|
|
l: buf,
|
|
formatter: defaultFormatter,
|
|
}
|
|
}
|
|
|
|
func (b FileBackend) Write(r *Record) error {
|
|
text := b.formatter(r)
|
|
|
|
_, err := io.WriteString(b.l, text)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot write logs: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetLevel changes the log level of the backend.
|
|
func (b *FileBackend) SetLevel(l Level) {
|
|
b.level = l
|
|
}
|
|
|
|
// Level returns the log level set for this backend.
|
|
func (b *FileBackend) Level() Level {
|
|
return b.level
|
|
}
|
|
|
|
// SetFormatter defines the formatter for this backend.
|
|
func (b *FileBackend) SetFormatter(f Formatter) {
|
|
b.formatter = f
|
|
}
|
|
|
|
// Reopen closes and reopens the file it writes to. It should be used after log
|
|
// rotation.
|
|
func (b *FileBackend) Reopen() error {
|
|
if err := b.Close(); err != nil {
|
|
return err
|
|
}
|
|
|
|
fd, err := os.OpenFile(b.filepath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o600)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot open log file %s: %w", b.filepath, err)
|
|
}
|
|
|
|
b.l = fd
|
|
|
|
return nil
|
|
}
|
|
|
|
// Close closes the underlying file used by the backend.
|
|
func (b *FileBackend) Close() error {
|
|
if b.filepath == "" {
|
|
return nil
|
|
}
|
|
|
|
if c, ok := b.l.(io.Closer); ok {
|
|
if err := c.Close(); err != nil {
|
|
return fmt.Errorf("cannot close log file: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
//
|
|
// Noop Backend
|
|
//
|
|
|
|
var _ Backend = &NoopBackend{}
|
|
|
|
// NoopBackend does nothing and discards all log entries without writing them anywhere.
|
|
type NoopBackend struct{}
|
|
|
|
// NewNoopBackend creates a noop backend.
|
|
func NewNoopBackend() (*NoopBackend, error) {
|
|
return &NoopBackend{}, nil
|
|
}
|
|
|
|
// Write is a noop.
|
|
func (*NoopBackend) Write(_ *Record) error {
|
|
return nil
|
|
}
|
|
|
|
// SetFormatter is a noop.
|
|
func (*NoopBackend) SetFormatter(_ Formatter) {}
|
|
|
|
// SetLevel is a noop.
|
|
func (*NoopBackend) SetLevel(_ Level) {}
|
|
|
|
// Level always returns DefeultLevel.
|
|
func (*NoopBackend) Level() Level {
|
|
return DefaultLevel
|
|
}
|
|
|
|
// Reopen is a noop.
|
|
func (*NoopBackend) Reopen() error {
|
|
return nil
|
|
}
|
|
|
|
// Close is a noop.
|
|
func (*NoopBackend) Close() error {
|
|
return nil
|
|
}
|