logging/logger.go

190 lines
4.7 KiB
Go

package logging
import (
"fmt"
"log"
"os"
"sync"
)
const exitCodeFatal = 100
// Logger is a facility that writes logs to one or more backands (files,
// stdout/stderr, syslog, etc.) which can be configured independently
//
// Loggers are concurrent-safe.
type Logger struct {
mutex sync.Mutex
name string
backends []Backend
}
// NewLogger initializes a new Logger with no backend and with the default log level.
func NewLogger(name string) *Logger {
l := &Logger{
name: name,
}
return l
}
// AddBackend add a new Backend to the logger. All set backends are kept.
func (l *Logger) AddBackend(b Backend) {
l.mutex.Lock()
defer l.mutex.Unlock()
l.backends = append(l.backends, b)
}
// SetBackend sets the backend list to the logger. Any existing backend will be lost.
func (l *Logger) SetBackend(b ...Backend) {
l.mutex.Lock()
defer l.mutex.Unlock()
l.backends = b
}
// SetLevel changes the log level of all regisered backends to the given level.
func (l *Logger) SetLevel(level Level) {
for _, backend := range l.backends {
backend.SetLevel(level)
}
}
type buffer struct {
logger *Logger
level Level
}
func (b *buffer) Write(p []byte) (int, error) {
b.logger.Log(b.level, string(p))
return len(p), nil
}
// AsStdLog encapsulate the logger in an instance of lof.Logger from the
// standard library and returns it.
//
// It is there for interoperability reasons.
func (l *Logger) AsStdLog(level Level) *log.Logger {
stdLogger := log.New(&buffer{logger: l, level: level}, "", 0)
return stdLogger
}
// Log sends a record containing the message `m` to the registered backends
// whose level is at least `level`.
func (l *Logger) Log(level Level, m string) {
l.mutex.Lock()
defer l.mutex.Unlock()
r := NewRecord(l.name, level, m)
for _, backend := range l.backends {
if r.Level >= backend.Level() {
if err := backend.Write(r); err != nil {
//revive:disable-next-line:unhandled-error stop error handling recursion!
fmt.Fprintf(os.Stderr, "Cannot write logs: %v", err)
}
}
}
}
// Trace logs a message with the Trace level.
func (l *Logger) Trace(text string) {
l.Log(Trace, text)
}
// Tracef formats the message with given args and logs the result with the
// Trace level.
func (l *Logger) Tracef(text string, args ...interface{}) {
l.Trace(fmt.Sprintf(text, args...))
}
// Debug logs a message with the Debug level.
func (l *Logger) Debug(text string) {
l.Log(Debug, text)
}
// Debugf formats the message with given args and logs the result with the
// Debug level.
func (l *Logger) Debugf(text string, args ...interface{}) {
l.Debug(fmt.Sprintf(text, args...))
}
// Info logs a message with the Info level.
func (l *Logger) Info(text string) {
l.Log(Info, text)
}
// Infof formats the message with given args and logs the result with the
// Info level.
func (l *Logger) Infof(text string, args ...interface{}) {
l.Info(fmt.Sprintf(text, args...))
}
// Notice logs a message with the Notice level.
func (l *Logger) Notice(text string) {
l.Log(Notice, text)
}
// Noticef formats the message with given args and logs the result with the
// Notice level.
func (l *Logger) Noticef(text string, args ...interface{}) {
l.Notice(fmt.Sprintf(text, args...))
}
// Warning logs a message with the Warning level.
func (l *Logger) Warning(text string) {
l.Log(Warning, text)
}
// Warningf formats the message with given args and logs the result with the
// Warning level.
func (l *Logger) Warningf(text string, args ...interface{}) {
l.Warning(fmt.Sprintf(text, args...))
}
// Error logs a message with the Error level.
func (l *Logger) Error(text string) {
l.Log(Error, text)
}
// Errorf formats the message with given args and logs the result with the
// Error level.
func (l *Logger) Errorf(text string, args ...interface{}) {
l.Error(fmt.Sprintf(text, args...))
}
// Critical logs a message with the Critical level.
func (l *Logger) Critical(text string) {
l.Log(Critical, text)
}
// Criticalf formats the message with given args and logs the result with the.
// Critical level.
func (l *Logger) Criticalf(text string, args ...interface{}) {
l.Critical(fmt.Sprintf(text, args...))
}
// Alert logs a message with the Alert level.
func (l *Logger) Alert(text string) {
l.Log(Alert, text)
}
// Alertf formats the message with given args and logs the result with the.
// Alert level.
func (l *Logger) Alertf(text string, args ...interface{}) {
l.Alert(fmt.Sprintf(text, args...))
}
// Fatal logs a message with the Fatal level.
func (l *Logger) Fatal(text string) {
l.Log(Debug, text)
os.Exit(exitCodeFatal) //nolint:revive // This is wanted if fatal is called
}
// Fatalf formats the message with given args and logs the result with the
// Fatal level.
func (l *Logger) Fatalf(text string, args ...interface{}) {
l.Fatal(fmt.Sprintf(text, args...))
}