logging/backend.go

174 lines
3.5 KiB
Go
Raw Normal View History

2013-06-21 18:35:47 +02:00
package logging
import (
2013-06-24 17:37:46 +02:00
"fmt"
2013-06-21 18:35:47 +02:00
"io"
"os"
"path/filepath"
2013-06-21 18:35:47 +02:00
)
2020-02-01 17:30:09 +01:00
// Backend is the interface that specifies the methods that a backend must
// implement.
2013-06-21 18:35:47 +02:00
type Backend interface {
Write(*Record) error
SetFormatter(Formatter)
2013-06-24 17:37:46 +02:00
SetLevel(Level)
Level() Level
2014-12-04 20:25:49 +01:00
Reopen() error
2020-05-17 14:33:16 +02:00
Close() error
2013-06-21 18:35:47 +02:00
}
2013-06-24 17:37:46 +02:00
//
// Backend to write in file-like objects
//
var _ Backend = &FileBackend{}
2020-02-01 17:30:09 +01:00
// FileBackend is a backend that writes to a file.
2013-06-24 17:37:46 +02:00
type FileBackend struct {
formatter Formatter
2013-06-21 18:35:47 +02:00
l io.Writer
2014-12-04 20:25:49 +01:00
filepath string
level Level
2013-06-21 18:35:47 +02:00
}
2020-02-01 17:30:09 +01:00
// NewStdoutBackend creates a new backend to write the logs on the standard
// output.
func NewStdoutBackend() *FileBackend {
return &FileBackend{
2013-06-21 18:35:47 +02:00
l: os.Stdout,
formatter: defaultFormatter,
2013-06-21 18:35:47 +02:00
}
}
// NewStderrBackend creates a new backend to write the logs on the error output.
func NewStderrBackend() *FileBackend {
return &FileBackend{
2013-06-24 17:37:46 +02:00
l: os.Stderr,
formatter: defaultFormatter,
2013-06-24 17:37:46 +02:00
}
}
// NewFileBackend creates a new backend to write the logs in a given file.
2020-02-01 17:30:09 +01:00
func NewFileBackend(filename string) (*FileBackend, error) {
fd, err := os.OpenFile(filepath.Clean(filename),
os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o600)
2013-06-24 17:37:46 +02:00
if err != nil {
return nil, fmt.Errorf("cannot open log file %s: %w", filename, err)
2013-06-24 17:37:46 +02:00
}
2020-02-01 17:30:09 +01:00
b := &FileBackend{
l: fd,
formatter: defaultFormatter,
2014-12-04 20:25:49 +01:00
filepath: filename,
2013-06-24 17:37:46 +02:00
}
2020-02-01 17:30:09 +01:00
return b, nil
2013-06-24 17:37:46 +02:00
}
// 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,
}
}
2013-06-24 17:37:46 +02:00
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
2013-06-21 18:35:47 +02:00
}
// SetLevel changes the log level of the backend.
2013-06-24 17:37:46 +02:00
func (b *FileBackend) SetLevel(l Level) {
2013-06-21 18:35:47 +02:00
b.level = l
}
// Level returns the log level set for this backend.
2013-06-24 17:37:46 +02:00
func (b *FileBackend) Level() Level {
return b.level
}
// SetFormatter defines the formatter for this backend.
func (b *FileBackend) SetFormatter(f Formatter) {
2013-06-21 18:35:47 +02:00
b.formatter = f
}
2020-02-01 17:30:09 +01:00
// Reopen closes and reopens the file it writes to. It should be used after log
// rotation.
2014-12-04 20:25:49 +01:00
func (b *FileBackend) Reopen() error {
2020-05-17 14:33:16 +02:00
if err := b.Close(); err != nil {
return err
}
fd, err := os.OpenFile(b.filepath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o600)
2020-05-17 14:33:16 +02:00
if err != nil {
return fmt.Errorf("cannot open log file %s: %w", b.filepath, err)
2020-05-17 14:33:16 +02:00
}
b.l = fd
return nil
}
// Close closes the underlying file used by the backend.
2020-05-17 14:33:16 +02:00
func (b *FileBackend) Close() error {
2014-12-04 20:25:49 +01:00
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)
}
}
2014-12-04 20:25:49 +01:00
return nil
}
2014-10-22 12:35:14 +02:00
//
// Noop Backend
//
var _ Backend = &NoopBackend{}
// NoopBackend does nothing and discards all log entries without writing them anywhere.
2014-10-22 12:35:14 +02:00
type NoopBackend struct{}
// NewNoopBackend creates a noop backend.
func NewNoopBackend() (*NoopBackend, error) {
2014-10-22 12:35:14 +02:00
return &NoopBackend{}, nil
}
// Write is a noop.
func (*NoopBackend) Write(_ *Record) error {
2014-10-22 12:35:14 +02:00
return nil
}
// SetFormatter is a noop.
func (*NoopBackend) SetFormatter(_ Formatter) {}
2014-10-22 12:35:14 +02:00
// SetLevel is a noop.
func (*NoopBackend) SetLevel(_ Level) {}
2014-10-22 12:35:14 +02:00
// Level always returns DefeultLevel.
func (*NoopBackend) Level() Level {
return DefaultLevel
2014-10-22 12:35:14 +02:00
}
2014-12-04 20:25:49 +01:00
// Reopen is a noop.
func (*NoopBackend) Reopen() error {
2014-12-04 20:25:49 +01:00
return nil
}
2020-05-17 14:33:16 +02:00
// Close is a noop.
func (*NoopBackend) Close() error {
2020-05-17 14:33:16 +02:00
return nil
}