logger: update logger interface

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2021-01-10 18:56:39 +03:00
parent 270ad1b889
commit 7b3a7a9448
5 changed files with 111 additions and 84 deletions

View File

@ -12,12 +12,11 @@ const (
TraceLevel Level = iota - 2 TraceLevel Level = iota - 2
// DebugLevel level. Usually only enabled when debugging. Very verbose logging. // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
DebugLevel DebugLevel
// InfoLevel is the default logging priority. // InfoLevel level. General operational entries about what's going on inside the application.
// General operational entries about what's going on inside the application.
InfoLevel InfoLevel
// WarnLevel level. Non-critical entries that deserve eyes. // WarnLevel level. Non-critical entries that deserve eyes.
WarnLevel WarnLevel
// ErrorLevel level. Logs. Used for errors that should definitely be noted. // ErrorLevel level. Used for errors that should definitely be noted.
ErrorLevel ErrorLevel
// FatalLevel level. Logs and then calls `os.Exit(1)`. highest level of severity. // FatalLevel level. Logs and then calls `os.Exit(1)`. highest level of severity.
FatalLevel FatalLevel

View File

@ -1,9 +1,13 @@
// Package logger provides a log interface // Package logger provides a log interface
package logger package logger
import "context"
var ( var (
// DefaultLogger variable // DefaultLogger variable
DefaultLogger Logger = NewLogger() DefaultLogger Logger = NewLogger()
// DefaultLogger level
DefaultLevel Level = InfoLevel
) )
// Logger is a generic logging interface // Logger is a generic logging interface
@ -14,94 +18,100 @@ type Logger interface {
V(level Level) bool V(level Level) bool
// The Logger options // The Logger options
Options() Options Options() Options
// SetLevel modify current log level
SetLevel(level Level)
// Fields set fields to always be logged // Fields set fields to always be logged
Fields(fields map[string]interface{}) Logger Fields(fields map[string]interface{}) Logger
// Info level message // Info level message
Info(args ...interface{}) Info(ctx context.Context, args ...interface{})
// Trace level message // Trace level message
Trace(args ...interface{}) Trace(ctx context.Context, args ...interface{})
// Debug level message // Debug level message
Debug(args ...interface{}) Debug(ctx context.Context, args ...interface{})
// Warn level message // Warn level message
Warn(args ...interface{}) Warn(ctx context.Context, args ...interface{})
// Error level message // Error level message
Error(args ...interface{}) Error(ctx context.Context, args ...interface{})
// Fatal level message // Fatal level message
Fatal(args ...interface{}) Fatal(ctx context.Context, args ...interface{})
// Infof level message // Infof level message
Infof(msg string, args ...interface{}) Infof(ctx context.Context, msg string, args ...interface{})
// Tracef level message // Tracef level message
Tracef(msg string, args ...interface{}) Tracef(ctx context.Context, msg string, args ...interface{})
// Debug level message // Debug level message
Debugf(msg string, args ...interface{}) Debugf(ctx context.Context, msg string, args ...interface{})
// Warn level message // Warn level message
Warnf(msg string, args ...interface{}) Warnf(ctx context.Context, msg string, args ...interface{})
// Error level message // Error level message
Errorf(msg string, args ...interface{}) Errorf(ctx context.Context, msg string, args ...interface{})
// Fatal level message // Fatal level message
Fatalf(msg string, args ...interface{}) Fatalf(ctx context.Context, msg string, args ...interface{})
// Log logs message with needed level
Log(ctx context.Context, level Level, args ...interface{})
// Logf logs message with needed level
Logf(ctx context.Context, level Level, msg string, args ...interface{})
// String returns the name of logger // String returns the name of logger
String() string String() string
} }
// Info writes msg to default logger on info level // Info writes msg to default logger on info level
func Info(args ...interface{}) { func Info(ctx context.Context, args ...interface{}) {
DefaultLogger.Info(args...) DefaultLogger.Info(ctx, args...)
} }
// Error writes msg to default logger on error level // Error writes msg to default logger on error level
func Error(args ...interface{}) { func Error(ctx context.Context, args ...interface{}) {
DefaultLogger.Error(args...) DefaultLogger.Error(ctx, args...)
} }
// Debug writes msg to default logger on debug level // Debug writes msg to default logger on debug level
func Debug(args ...interface{}) { func Debug(ctx context.Context, args ...interface{}) {
DefaultLogger.Debug(args...) DefaultLogger.Debug(ctx, args...)
} }
// Warn writes msg to default logger on warn level // Warn writes msg to default logger on warn level
func Warn(args ...interface{}) { func Warn(ctx context.Context, args ...interface{}) {
DefaultLogger.Warn(args...) DefaultLogger.Warn(ctx, args...)
} }
// Trace writes msg to default logger on trace level // Trace writes msg to default logger on trace level
func Trace(args ...interface{}) { func Trace(ctx context.Context, args ...interface{}) {
DefaultLogger.Trace(args...) DefaultLogger.Trace(ctx, args...)
} }
// Fatal writes msg to default logger on fatal level // Fatal writes msg to default logger on fatal level
func Fatal(args ...interface{}) { func Fatal(ctx context.Context, args ...interface{}) {
DefaultLogger.Fatal(args...) DefaultLogger.Fatal(ctx, args...)
} }
// Infof writes formatted msg to default logger on info level // Infof writes formatted msg to default logger on info level
func Infof(msg string, args ...interface{}) { func Infof(ctx context.Context, msg string, args ...interface{}) {
DefaultLogger.Infof(msg, args...) DefaultLogger.Infof(ctx, msg, args...)
} }
// Errorf writes formatted msg to default logger on error level // Errorf writes formatted msg to default logger on error level
func Errorf(msg string, args ...interface{}) { func Errorf(ctx context.Context, msg string, args ...interface{}) {
DefaultLogger.Errorf(msg, args...) DefaultLogger.Errorf(ctx, msg, args...)
} }
// Debugf writes formatted msg to default logger on debug level // Debugf writes formatted msg to default logger on debug level
func Debugf(msg string, args ...interface{}) { func Debugf(ctx context.Context, msg string, args ...interface{}) {
DefaultLogger.Debugf(msg, args...) DefaultLogger.Debugf(ctx, msg, args...)
} }
// Warnf writes formatted msg to default logger on warn level // Warnf writes formatted msg to default logger on warn level
func Warnf(msg string, args ...interface{}) { func Warnf(ctx context.Context, msg string, args ...interface{}) {
DefaultLogger.Warnf(msg, args...) DefaultLogger.Warnf(ctx, msg, args...)
} }
// Tracef writes formatted msg to default logger on trace level // Tracef writes formatted msg to default logger on trace level
func Tracef(msg string, args ...interface{}) { func Tracef(ctx context.Context, msg string, args ...interface{}) {
DefaultLogger.Tracef(msg, args...) DefaultLogger.Tracef(ctx, msg, args...)
} }
// Fatalf writes formatted msg to default logger on fatal level // Fatalf writes formatted msg to default logger on fatal level
func Fatalf(msg string, args ...interface{}) { func Fatalf(ctx context.Context, msg string, args ...interface{}) {
DefaultLogger.Fatalf(msg, args...) DefaultLogger.Fatalf(ctx, msg, args...)
} }
// V returns true if passed level enabled in default logger // V returns true if passed level enabled in default logger

View File

@ -1,16 +1,18 @@
package logger package logger
import ( import (
"context"
"testing" "testing"
) )
func TestLogger(t *testing.T) { func TestLogger(t *testing.T) {
ctx := context.TODO()
l := NewLogger(WithLevel(TraceLevel)) l := NewLogger(WithLevel(TraceLevel))
if err := l.Init(); err != nil { if err := l.Init(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
l.Trace("trace_msg1") l.Trace(ctx, "trace_msg1")
l.Warn("warn_msg1") l.Warn(ctx, "warn_msg1")
l.Fields(map[string]interface{}{"error": "test"}).Info("error message") l.Fields(map[string]interface{}{"error": "test"}).Info(ctx, "error message")
l.Warn("first", " ", "second") l.Warn(ctx, "first", " ", "second")
} }

View File

@ -1,6 +1,7 @@
package logger package logger
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
@ -28,12 +29,11 @@ type defaultLogger struct {
// Init(opts...) should only overwrite provided options // Init(opts...) should only overwrite provided options
func (l *defaultLogger) Init(opts ...Option) error { func (l *defaultLogger) Init(opts ...Option) error {
l.Lock() l.Lock()
defer l.Unlock()
for _, o := range opts { for _, o := range opts {
o(&l.opts) o(&l.opts)
} }
l.enc = json.NewEncoder(l.opts.Out) l.enc = json.NewEncoder(l.opts.Out)
l.Unlock()
return nil return nil
} }
@ -41,8 +41,24 @@ func (l *defaultLogger) String() string {
return "micro" return "micro"
} }
func (l *defaultLogger) SetLevel(level Level) {
l.Lock()
l.opts.Level = level
l.Unlock()
}
func (l *defaultLogger) GetLevel() Level {
l.RLock()
lvl := l.opts.Level
l.RUnlock()
return lvl
}
func (l *defaultLogger) V(level Level) bool { func (l *defaultLogger) V(level Level) bool {
return l.opts.Level.Enabled(level) l.RLock()
ok := l.opts.Level.Enabled(level)
l.RUnlock()
return ok
} }
func (l *defaultLogger) Fields(fields map[string]interface{}) Logger { func (l *defaultLogger) Fields(fields map[string]interface{}) Logger {
@ -84,57 +100,57 @@ func logCallerfilePath(loggingFilePath string) string {
return loggingFilePath[idx+1:] return loggingFilePath[idx+1:]
} }
func (l *defaultLogger) Info(args ...interface{}) { func (l *defaultLogger) Info(ctx context.Context, args ...interface{}) {
l.log(InfoLevel, args...) l.Log(ctx, InfoLevel, args...)
} }
func (l *defaultLogger) Error(args ...interface{}) { func (l *defaultLogger) Error(ctx context.Context, args ...interface{}) {
l.log(ErrorLevel, args...) l.Log(ctx, ErrorLevel, args...)
} }
func (l *defaultLogger) Debug(args ...interface{}) { func (l *defaultLogger) Debug(ctx context.Context, args ...interface{}) {
l.log(DebugLevel, args...) l.Log(ctx, DebugLevel, args...)
} }
func (l *defaultLogger) Warn(args ...interface{}) { func (l *defaultLogger) Warn(ctx context.Context, args ...interface{}) {
l.log(WarnLevel, args...) l.Log(ctx, WarnLevel, args...)
} }
func (l *defaultLogger) Trace(args ...interface{}) { func (l *defaultLogger) Trace(ctx context.Context, args ...interface{}) {
l.log(TraceLevel, args...) l.Log(ctx, TraceLevel, args...)
} }
func (l *defaultLogger) Fatal(args ...interface{}) { func (l *defaultLogger) Fatal(ctx context.Context, args ...interface{}) {
l.log(FatalLevel, args...) l.Log(ctx, FatalLevel, args...)
os.Exit(1) os.Exit(1)
} }
func (l *defaultLogger) Infof(msg string, args ...interface{}) { func (l *defaultLogger) Infof(ctx context.Context, msg string, args ...interface{}) {
l.logf(InfoLevel, msg, args...) l.Logf(ctx, InfoLevel, msg, args...)
} }
func (l *defaultLogger) Errorf(msg string, args ...interface{}) { func (l *defaultLogger) Errorf(ctx context.Context, msg string, args ...interface{}) {
l.logf(ErrorLevel, msg, args...) l.Logf(ctx, ErrorLevel, msg, args...)
} }
func (l *defaultLogger) Debugf(msg string, args ...interface{}) { func (l *defaultLogger) Debugf(ctx context.Context, msg string, args ...interface{}) {
l.logf(DebugLevel, msg, args...) l.Logf(ctx, DebugLevel, msg, args...)
} }
func (l *defaultLogger) Warnf(msg string, args ...interface{}) { func (l *defaultLogger) Warnf(ctx context.Context, msg string, args ...interface{}) {
l.logf(WarnLevel, msg, args...) l.Logf(ctx, WarnLevel, msg, args...)
} }
func (l *defaultLogger) Tracef(msg string, args ...interface{}) { func (l *defaultLogger) Tracef(ctx context.Context, msg string, args ...interface{}) {
l.logf(TraceLevel, msg, args...) l.Logf(ctx, TraceLevel, msg, args...)
} }
func (l *defaultLogger) Fatalf(msg string, args ...interface{}) { func (l *defaultLogger) Fatalf(ctx context.Context, msg string, args ...interface{}) {
l.logf(FatalLevel, msg, args...) l.Logf(ctx, FatalLevel, msg, args...)
os.Exit(1) os.Exit(1)
} }
func (l *defaultLogger) log(level Level, args ...interface{}) { func (l *defaultLogger) Log(ctx context.Context, level Level, args ...interface{}) {
if !l.V(level) { if !l.V(level) {
return return
} }
@ -157,7 +173,7 @@ func (l *defaultLogger) log(level Level, args ...interface{}) {
l.RUnlock() l.RUnlock()
} }
func (l *defaultLogger) logf(level Level, msg string, args ...interface{}) { func (l *defaultLogger) Logf(ctx context.Context, level Level, msg string, args ...interface{}) {
if !l.V(level) { if !l.V(level) {
return return
} }

View File

@ -26,10 +26,10 @@ type Options struct {
// NewOptions creates new options struct // NewOptions creates new options struct
func NewOptions(opts ...Option) Options { func NewOptions(opts ...Option) Options {
options := Options{ options := Options{
Level: InfoLevel, Level: DefaultLevel,
Fields: make(map[string]interface{}), Fields: make(map[string]interface{}),
Out: os.Stderr, Out: os.Stderr,
CallerSkipCount: 2, CallerSkipCount: 0,
Context: context.Background(), Context: context.Background(),
} }
for _, o := range opts { for _, o := range opts {
@ -40,35 +40,35 @@ func NewOptions(opts ...Option) Options {
// WithFields set default fields for the logger // WithFields set default fields for the logger
func WithFields(fields map[string]interface{}) Option { func WithFields(fields map[string]interface{}) Option {
return func(args *Options) { return func(o *Options) {
args.Fields = fields o.Fields = fields
} }
} }
// WithLevel set default level for the logger // WithLevel set default level for the logger
func WithLevel(level Level) Option { func WithLevel(level Level) Option {
return func(args *Options) { return func(o *Options) {
args.Level = level o.Level = level
} }
} }
// WithOutput set default output writer for the logger // WithOutput set default output writer for the logger
func WithOutput(out io.Writer) Option { func WithOutput(out io.Writer) Option {
return func(args *Options) { return func(o *Options) {
args.Out = out o.Out = out
} }
} }
// WithCallerSkipCount set frame count to skip // WithCallerSkipCount set frame count to skip
func WithCallerSkipCount(c int) Option { func WithCallerSkipCount(c int) Option {
return func(args *Options) { return func(o *Options) {
args.CallerSkipCount = c o.CallerSkipCount = c
} }
} }
// WithContext set context // WithContext set context
func WithContext(ctx context.Context) Option { func WithContext(ctx context.Context) Option {
return func(args *Options) { return func(o *Options) {
args.Context = ctx o.Context = ctx
} }
} }