2020-03-09 22:11:16 +08:00
|
|
|
// Copyright 2020 Kentaro Hibino. All rights reserved.
|
|
|
|
// Use of this source code is governed by a MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
// Package log exports logging related types and functions.
|
|
|
|
package log
|
|
|
|
|
|
|
|
import (
|
2020-05-06 13:10:11 +08:00
|
|
|
"fmt"
|
2020-03-09 22:11:16 +08:00
|
|
|
"io"
|
|
|
|
stdlog "log"
|
2020-03-12 22:31:10 +08:00
|
|
|
"os"
|
2020-05-08 12:28:06 +08:00
|
|
|
"sync"
|
2020-03-09 22:11:16 +08:00
|
|
|
)
|
|
|
|
|
2020-05-10 01:59:50 +08:00
|
|
|
// Base supports logging at various log levels.
|
2020-05-06 13:10:11 +08:00
|
|
|
type Base interface {
|
|
|
|
// Debug logs a message at Debug level.
|
|
|
|
Debug(args ...interface{})
|
|
|
|
|
|
|
|
// Info logs a message at Info level.
|
|
|
|
Info(args ...interface{})
|
|
|
|
|
|
|
|
// Warn logs a message at Warning level.
|
|
|
|
Warn(args ...interface{})
|
|
|
|
|
|
|
|
// Error logs a message at Error level.
|
|
|
|
Error(args ...interface{})
|
|
|
|
|
|
|
|
// Fatal logs a message at Fatal level
|
|
|
|
// and process will exit with status set to 1.
|
|
|
|
Fatal(args ...interface{})
|
2020-03-09 22:11:16 +08:00
|
|
|
}
|
|
|
|
|
2020-05-06 13:10:11 +08:00
|
|
|
// baseLogger is a wrapper object around log.Logger from the standard library.
|
2020-03-14 11:53:31 +08:00
|
|
|
// It supports logging at various log levels.
|
2020-05-06 13:10:11 +08:00
|
|
|
type baseLogger struct {
|
2020-03-09 22:11:16 +08:00
|
|
|
*stdlog.Logger
|
|
|
|
}
|
|
|
|
|
2020-03-14 11:53:31 +08:00
|
|
|
// Debug logs a message at Debug level.
|
2020-05-06 13:10:11 +08:00
|
|
|
func (l *baseLogger) Debug(args ...interface{}) {
|
|
|
|
l.prefixPrint("DEBUG: ", args...)
|
2020-03-12 22:31:10 +08:00
|
|
|
}
|
|
|
|
|
2020-03-14 11:53:31 +08:00
|
|
|
// Info logs a message at Info level.
|
2020-05-06 13:10:11 +08:00
|
|
|
func (l *baseLogger) Info(args ...interface{}) {
|
|
|
|
l.prefixPrint("INFO: ", args...)
|
2020-03-09 22:11:16 +08:00
|
|
|
}
|
|
|
|
|
2020-03-14 11:53:31 +08:00
|
|
|
// Warn logs a message at Warning level.
|
2020-05-06 13:10:11 +08:00
|
|
|
func (l *baseLogger) Warn(args ...interface{}) {
|
|
|
|
l.prefixPrint("WARN: ", args...)
|
2020-03-09 22:11:16 +08:00
|
|
|
}
|
|
|
|
|
2020-03-14 11:53:31 +08:00
|
|
|
// Error logs a message at Error level.
|
2020-05-06 13:10:11 +08:00
|
|
|
func (l *baseLogger) Error(args ...interface{}) {
|
|
|
|
l.prefixPrint("ERROR: ", args...)
|
2020-03-09 22:11:16 +08:00
|
|
|
}
|
2020-03-12 22:31:10 +08:00
|
|
|
|
2020-03-14 11:53:31 +08:00
|
|
|
// Fatal logs a message at Fatal level
|
|
|
|
// and process will exit with status set to 1.
|
2020-05-06 13:10:11 +08:00
|
|
|
func (l *baseLogger) Fatal(args ...interface{}) {
|
|
|
|
l.prefixPrint("FATAL: ", args...)
|
2020-03-12 22:31:10 +08:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
2020-05-06 13:10:11 +08:00
|
|
|
|
|
|
|
func (l *baseLogger) prefixPrint(prefix string, args ...interface{}) {
|
|
|
|
args = append([]interface{}{prefix}, args...)
|
|
|
|
l.Print(args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// newBase creates and returns a new instance of baseLogger.
|
|
|
|
func newBase(out io.Writer) *baseLogger {
|
|
|
|
prefix := fmt.Sprintf("asynq: pid=%d ", os.Getpid())
|
|
|
|
return &baseLogger{
|
|
|
|
stdlog.New(out, prefix, stdlog.Ldate|stdlog.Ltime|stdlog.Lmicroseconds|stdlog.LUTC),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewLogger creates and returns a new instance of Logger.
|
2020-05-08 12:28:06 +08:00
|
|
|
// Log level is set to DebugLevel by default.
|
2020-05-06 13:10:11 +08:00
|
|
|
func NewLogger(base Base) *Logger {
|
|
|
|
if base == nil {
|
|
|
|
base = newBase(os.Stderr)
|
|
|
|
}
|
2020-05-08 12:28:06 +08:00
|
|
|
return &Logger{base: base, level: DebugLevel}
|
2020-05-06 13:10:11 +08:00
|
|
|
}
|
|
|
|
|
2020-05-10 01:59:50 +08:00
|
|
|
// Logger logs message to io.Writer at various log levels.
|
2020-05-06 13:10:11 +08:00
|
|
|
type Logger struct {
|
2020-05-08 12:28:06 +08:00
|
|
|
base Base
|
|
|
|
|
|
|
|
mu sync.Mutex
|
|
|
|
// Minimum log level for this logger.
|
|
|
|
// Message with level lower than this level won't be outputted.
|
|
|
|
level Level
|
|
|
|
}
|
|
|
|
|
|
|
|
// Level represents a log level.
|
|
|
|
type Level int32
|
|
|
|
|
|
|
|
const (
|
|
|
|
// DebugLevel is the lowest level of logging.
|
|
|
|
// Debug logs are intended for debugging and development purposes.
|
|
|
|
DebugLevel Level = iota
|
|
|
|
|
|
|
|
// InfoLevel is used for general informational log messages.
|
|
|
|
InfoLevel
|
|
|
|
|
|
|
|
// WarnLevel is used for undesired but relatively expected events,
|
|
|
|
// which may indicate a problem.
|
|
|
|
WarnLevel
|
|
|
|
|
|
|
|
// ErrorLevel is used for undesired and unexpected events that
|
|
|
|
// the program can recover from.
|
|
|
|
ErrorLevel
|
|
|
|
|
|
|
|
// FatalLevel is used for undesired and unexpected events that
|
|
|
|
// the program cannot recover from.
|
|
|
|
FatalLevel
|
|
|
|
)
|
|
|
|
|
2020-05-10 01:59:50 +08:00
|
|
|
// String is part of the fmt.Stringer interface.
|
|
|
|
//
|
|
|
|
// Used for testing and debugging purposes.
|
2020-05-08 12:28:06 +08:00
|
|
|
func (l Level) String() string {
|
|
|
|
switch l {
|
|
|
|
case DebugLevel:
|
|
|
|
return "debug"
|
|
|
|
case InfoLevel:
|
|
|
|
return "info"
|
|
|
|
case WarnLevel:
|
|
|
|
return "warning"
|
|
|
|
case ErrorLevel:
|
|
|
|
return "error"
|
|
|
|
case FatalLevel:
|
|
|
|
return "fatal"
|
|
|
|
default:
|
|
|
|
return "unknown"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// canLogAt reports whether logger can log at level v.
|
|
|
|
func (l *Logger) canLogAt(v Level) bool {
|
|
|
|
l.mu.Lock()
|
|
|
|
defer l.mu.Unlock()
|
|
|
|
return v >= l.level
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Debug(args ...interface{}) {
|
|
|
|
if !l.canLogAt(DebugLevel) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
l.base.Debug(args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Info(args ...interface{}) {
|
|
|
|
if !l.canLogAt(InfoLevel) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
l.base.Info(args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Warn(args ...interface{}) {
|
|
|
|
if !l.canLogAt(WarnLevel) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
l.base.Warn(args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Error(args ...interface{}) {
|
2020-05-10 01:59:50 +08:00
|
|
|
if !l.canLogAt(ErrorLevel) {
|
2020-05-08 12:28:06 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
l.base.Error(args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Fatal(args ...interface{}) {
|
2020-05-10 01:59:50 +08:00
|
|
|
if !l.canLogAt(FatalLevel) {
|
2020-05-08 12:28:06 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
l.base.Fatal(args...)
|
2020-05-06 13:10:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Debugf(format string, args ...interface{}) {
|
|
|
|
l.Debug(fmt.Sprintf(format, args...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Infof(format string, args ...interface{}) {
|
|
|
|
l.Info(fmt.Sprintf(format, args...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Warnf(format string, args ...interface{}) {
|
|
|
|
l.Warn(fmt.Sprintf(format, args...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Errorf(format string, args ...interface{}) {
|
|
|
|
l.Error(fmt.Sprintf(format, args...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *Logger) Fatalf(format string, args ...interface{}) {
|
|
|
|
l.Fatal(fmt.Sprintf(format, args...))
|
|
|
|
}
|
2020-05-08 12:28:06 +08:00
|
|
|
|
|
|
|
// SetLevel sets the logger level.
|
|
|
|
// It panics if v is less than DebugLevel or greater than FatalLevel.
|
|
|
|
func (l *Logger) SetLevel(v Level) {
|
|
|
|
l.mu.Lock()
|
|
|
|
defer l.mu.Unlock()
|
|
|
|
if v < DebugLevel || v > FatalLevel {
|
|
|
|
panic("log: invalid log level")
|
|
|
|
}
|
|
|
|
l.level = v
|
|
|
|
}
|