mirror of
https://github.com/hibiken/asynq.git
synced 2024-11-10 11:31:58 +08:00
Allow setting minimum log level for logger
This commit is contained in:
parent
b63476ddc8
commit
d13f7e900f
@ -10,6 +10,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
stdlog "log"
|
stdlog "log"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Base supports logging with various log levels.
|
// Base supports logging with various log levels.
|
||||||
@ -78,16 +79,105 @@ func newBase(out io.Writer) *baseLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewLogger creates and returns a new instance of Logger.
|
// NewLogger creates and returns a new instance of Logger.
|
||||||
|
// Log level is set to DebugLevel by default.
|
||||||
func NewLogger(base Base) *Logger {
|
func NewLogger(base Base) *Logger {
|
||||||
if base == nil {
|
if base == nil {
|
||||||
base = newBase(os.Stderr)
|
base = newBase(os.Stderr)
|
||||||
}
|
}
|
||||||
return &Logger{base}
|
return &Logger{base: base, level: DebugLevel}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logger logs message to io.Writer with various log levels.
|
// Logger logs message to io.Writer with various log levels.
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
Base
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
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{}) {
|
||||||
|
if !l.canLogAt(WarnLevel) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l.base.Error(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Fatal(args ...interface{}) {
|
||||||
|
if !l.canLogAt(WarnLevel) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l.base.Fatal(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Logger) Debugf(format string, args ...interface{}) {
|
func (l *Logger) Debugf(format string, args ...interface{}) {
|
||||||
@ -109,3 +199,14 @@ func (l *Logger) Errorf(format string, args ...interface{}) {
|
|||||||
func (l *Logger) Fatalf(format string, args ...interface{}) {
|
func (l *Logger) Fatalf(format string, args ...interface{}) {
|
||||||
l.Fatal(fmt.Sprintf(format, args...))
|
l.Fatal(fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
@ -283,3 +283,54 @@ func TestLoggerErrorf(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoggerWithMinLevels(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
level Level
|
||||||
|
op string
|
||||||
|
}{
|
||||||
|
// with level one above
|
||||||
|
{InfoLevel, "Debug"},
|
||||||
|
{InfoLevel, "Debugf"},
|
||||||
|
{WarnLevel, "Info"},
|
||||||
|
{WarnLevel, "Infof"},
|
||||||
|
{ErrorLevel, "Warn"},
|
||||||
|
{ErrorLevel, "Warnf"},
|
||||||
|
{FatalLevel, "Error"},
|
||||||
|
{FatalLevel, "Errorf"},
|
||||||
|
// with skip level
|
||||||
|
{WarnLevel, "Debug"},
|
||||||
|
{ErrorLevel, "Infof"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
logger := NewLogger(newBase(&buf))
|
||||||
|
logger.SetLevel(tc.level)
|
||||||
|
|
||||||
|
switch tc.op {
|
||||||
|
case "Debug":
|
||||||
|
logger.Debug("hello")
|
||||||
|
case "Debugf":
|
||||||
|
logger.Debugf("hello, %s", "world")
|
||||||
|
case "Info":
|
||||||
|
logger.Info("hello")
|
||||||
|
case "Infof":
|
||||||
|
logger.Infof("hello, %s", "world")
|
||||||
|
case "Warn":
|
||||||
|
logger.Warn("hello")
|
||||||
|
case "Warnf":
|
||||||
|
logger.Warnf("hello, %s", "world")
|
||||||
|
case "Error":
|
||||||
|
logger.Error("hello")
|
||||||
|
case "Errorf":
|
||||||
|
logger.Errorf("hello, %s", "world")
|
||||||
|
default:
|
||||||
|
t.Fatalf("unexpected op: %q", tc.op)
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf.String() != "" {
|
||||||
|
t.Errorf("logger.%s outputted log message when level is set to %v", tc.op, tc.level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
32
server.go
32
server.go
@ -112,6 +112,11 @@ type Config struct {
|
|||||||
// If unset, default logger is used.
|
// If unset, default logger is used.
|
||||||
Logger Logger
|
Logger Logger
|
||||||
|
|
||||||
|
// LogLevel specifies the minimum log level to enable.
|
||||||
|
//
|
||||||
|
// If unset, DebugLevel is used by default.
|
||||||
|
LogLevel LogLevel
|
||||||
|
|
||||||
// ShutdownTimeout specifies the duration to wait to let workers finish their tasks
|
// ShutdownTimeout specifies the duration to wait to let workers finish their tasks
|
||||||
// before forcing them to abort when stopping the server.
|
// before forcing them to abort when stopping the server.
|
||||||
//
|
//
|
||||||
@ -152,6 +157,30 @@ type Logger interface {
|
|||||||
Fatal(args ...interface{})
|
Fatal(args ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogLevel represents logging level.
|
||||||
|
type LogLevel int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DebugLevel is the lowest level of logging.
|
||||||
|
// Debug logs are intended for debugging and development purposes.
|
||||||
|
DebugLevel LogLevel = 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
|
||||||
|
)
|
||||||
|
|
||||||
// Formula taken from https://github.com/mperham/sidekiq.
|
// Formula taken from https://github.com/mperham/sidekiq.
|
||||||
func defaultDelayFunc(n int, e error, t *Task) time.Duration {
|
func defaultDelayFunc(n int, e error, t *Task) time.Duration {
|
||||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
@ -189,6 +218,8 @@ func NewServer(r RedisConnOpt, cfg Config) *Server {
|
|||||||
if shutdownTimeout == 0 {
|
if shutdownTimeout == 0 {
|
||||||
shutdownTimeout = defaultShutdownTimeout
|
shutdownTimeout = defaultShutdownTimeout
|
||||||
}
|
}
|
||||||
|
logger := log.NewLogger(cfg.Logger)
|
||||||
|
logger.SetLevel(log.Level(cfg.LogLevel))
|
||||||
|
|
||||||
host, err := os.Hostname()
|
host, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -197,7 +228,6 @@ func NewServer(r RedisConnOpt, cfg Config) *Server {
|
|||||||
pid := os.Getpid()
|
pid := os.Getpid()
|
||||||
|
|
||||||
rdb := rdb.NewRDB(createRedisClient(r))
|
rdb := rdb.NewRDB(createRedisClient(r))
|
||||||
logger := log.NewLogger(cfg.Logger)
|
|
||||||
ss := base.NewServerState(host, pid, n, queues, cfg.StrictPriority)
|
ss := base.NewServerState(host, pid, n, queues, cfg.StrictPriority)
|
||||||
syncCh := make(chan *syncRequest)
|
syncCh := make(chan *syncRequest)
|
||||||
cancels := base.NewCancelations()
|
cancels := base.NewCancelations()
|
||||||
|
Loading…
Reference in New Issue
Block a user