2
0
mirror of https://github.com/hibiken/asynq.git synced 2024-12-25 07:12:17 +08:00

Change LogLevel to satisfy flag.Value interface

This commit is contained in:
Ken Hibino 2020-05-09 10:59:50 -07:00
parent 00b82904c6
commit 73d62844e6
4 changed files with 129 additions and 6 deletions

View File

@ -13,7 +13,7 @@ import (
"sync" "sync"
) )
// Base supports logging with various log levels. // Base supports logging at various log levels.
type Base interface { type Base interface {
// Debug logs a message at Debug level. // Debug logs a message at Debug level.
Debug(args ...interface{}) Debug(args ...interface{})
@ -87,7 +87,7 @@ func NewLogger(base Base) *Logger {
return &Logger{base: base, level: DebugLevel} return &Logger{base: base, level: DebugLevel}
} }
// Logger logs message to io.Writer with various log levels. // Logger logs message to io.Writer at various log levels.
type Logger struct { type Logger struct {
base Base base Base
@ -121,6 +121,9 @@ const (
FatalLevel FatalLevel
) )
// String is part of the fmt.Stringer interface.
//
// Used for testing and debugging purposes.
func (l Level) String() string { func (l Level) String() string {
switch l { switch l {
case DebugLevel: case DebugLevel:
@ -167,14 +170,14 @@ func (l *Logger) Warn(args ...interface{}) {
} }
func (l *Logger) Error(args ...interface{}) { func (l *Logger) Error(args ...interface{}) {
if !l.canLogAt(WarnLevel) { if !l.canLogAt(ErrorLevel) {
return return
} }
l.base.Error(args...) l.base.Error(args...)
} }
func (l *Logger) Fatal(args ...interface{}) { func (l *Logger) Fatal(args ...interface{}) {
if !l.canLogAt(WarnLevel) { if !l.canLogAt(FatalLevel) {
return return
} }
l.base.Fatal(args...) l.base.Fatal(args...)

View File

@ -284,7 +284,9 @@ func TestLoggerErrorf(t *testing.T) {
} }
} }
func TestLoggerWithMinLevels(t *testing.T) { func TestLoggerWithLowerLevels(t *testing.T) {
// Logger should not log messages at a level
// lower than the specified level.
tests := []struct { tests := []struct {
level Level level Level
op string op string
@ -334,3 +336,53 @@ func TestLoggerWithMinLevels(t *testing.T) {
} }
} }
} }
func TestLoggerWithSameOrHigherLevels(t *testing.T) {
// Logger should log messages at a level
// same as or higher than the specified level.
tests := []struct {
level Level
op string
}{
// same level
{DebugLevel, "Debug"},
{InfoLevel, "Infof"},
{WarnLevel, "Warn"},
{ErrorLevel, "Errorf"},
// higher level
{DebugLevel, "Info"},
{InfoLevel, "Warnf"},
{WarnLevel, "Error"},
}
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 did not output log message when level is set to %v", tc.op, tc.level)
}
}
}

View File

@ -12,6 +12,7 @@ import (
"math/rand" "math/rand"
"os" "os"
"runtime" "runtime"
"strings"
"sync" "sync"
"time" "time"
@ -138,7 +139,7 @@ func (fn ErrorHandlerFunc) HandleError(task *Task, err error, retried, maxRetry
fn(task, err, retried, maxRetry) fn(task, err, retried, maxRetry)
} }
// Logger supports logging with various log levels. // Logger supports logging at various log levels.
type Logger interface { type Logger interface {
// Debug logs a message at Debug level. // Debug logs a message at Debug level.
Debug(args ...interface{}) Debug(args ...interface{})
@ -158,6 +159,8 @@ type Logger interface {
} }
// LogLevel represents logging level. // LogLevel represents logging level.
//
// It satisfies flag.Value interface.
type LogLevel int32 type LogLevel int32
const ( const (
@ -181,6 +184,42 @@ const (
FatalLevel FatalLevel
) )
// String is part of the flag.Value interface.
func (l *LogLevel) String() string {
switch *l {
case DebugLevel:
return "debug"
case InfoLevel:
return "info"
case WarnLevel:
return "warn"
case ErrorLevel:
return "error"
case FatalLevel:
return "fatal"
}
panic(fmt.Sprintf("asynq: unexpected log level: %v", *l))
}
// Set is part of the flag.Value interface.
func (l *LogLevel) Set(val string) error {
switch strings.ToLower(val) {
case "debug":
*l = DebugLevel
case "info":
*l = InfoLevel
case "warn", "warning":
*l = WarnLevel
case "error":
*l = ErrorLevel
case "fatal":
*l = FatalLevel
default:
return fmt.Errorf("asynq: unsupported log level %q", val)
}
return nil
}
// 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()))

View File

@ -208,3 +208,32 @@ func TestServerWithFlakyBroker(t *testing.T) {
srv.Stop() srv.Stop()
} }
func TestLogLevel(t *testing.T) {
tests := []struct {
flagVal string
want LogLevel
wantStr string
}{
{"debug", DebugLevel, "debug"},
{"Info", InfoLevel, "info"},
{"WARN", WarnLevel, "warn"},
{"warning", WarnLevel, "warn"},
{"Error", ErrorLevel, "error"},
{"fatal", FatalLevel, "fatal"},
}
for _, tc := range tests {
level := new(LogLevel)
if err := level.Set(tc.flagVal); err != nil {
t.Fatal(err)
}
if *level != tc.want {
t.Errorf("Set(%q): got %v, want %v", tc.flagVal, level, &tc.want)
continue
}
if got := level.String(); got != tc.wantStr {
t.Errorf("String() returned %q, want %q", got, tc.wantStr)
}
}
}