logger with helper methods (#1216)
* support unix daemon socket * refactor(logger): logger fields changed to map[string]interface{} * improvement(logger): adding string to Level Parser * improvement(logger): rename ParseLevel to GetLevel * refactor(logger): adding basic logger adding micro default logger, and refactor logger interface * refactor(logger): moved basic logger to top level package * refactor(logger): adding default logger
This commit is contained in:
parent
88457b812e
commit
3fa7c26946
96
logger/default.go
Normal file
96
logger/default.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type defaultLogger struct {
|
||||||
|
opts Options
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init(opts...) should only overwrite provided options
|
||||||
|
func (l *defaultLogger) Init(opts ...Option) error {
|
||||||
|
for _, o := range opts {
|
||||||
|
o(&l.opts)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *defaultLogger) String() string {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *defaultLogger) Fields(fields map[string]interface{}) Logger {
|
||||||
|
l.opts.Fields = fields
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *defaultLogger) Error(err error) Logger {
|
||||||
|
l.err = err
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *defaultLogger) Log(level Level, v ...interface{}) {
|
||||||
|
if !l.opts.Level.Enabled(level) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := fmt.Sprint(v...)
|
||||||
|
|
||||||
|
fields := l.opts.Fields
|
||||||
|
fields["level"] = level.String()
|
||||||
|
fields["message"] = msg
|
||||||
|
if l.err != nil {
|
||||||
|
fields["error"] = l.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := json.NewEncoder(l.opts.Out)
|
||||||
|
|
||||||
|
if err := enc.Encode(fields); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *defaultLogger) Logf(level Level, format string, v ...interface{}) {
|
||||||
|
if level < l.opts.Level {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := fmt.Sprintf(format, v...)
|
||||||
|
|
||||||
|
fields := l.opts.Fields
|
||||||
|
fields["level"] = level.String()
|
||||||
|
fields["message"] = msg
|
||||||
|
if l.err != nil {
|
||||||
|
fields["error"] = l.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := json.NewEncoder(l.opts.Out)
|
||||||
|
|
||||||
|
if err := enc.Encode(fields); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *defaultLogger) Options() Options {
|
||||||
|
return n.opts
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLogger builds a new logger based on options
|
||||||
|
func NewLogger(opts ...Option) Logger {
|
||||||
|
// Default options
|
||||||
|
options := Options{
|
||||||
|
Level: InfoLevel,
|
||||||
|
Fields: make(map[string]interface{}),
|
||||||
|
Out: os.Stderr,
|
||||||
|
Context: context.Background(),
|
||||||
|
}
|
||||||
|
|
||||||
|
l := &defaultLogger{opts: options}
|
||||||
|
_ = l.Init(opts...)
|
||||||
|
return l
|
||||||
|
}
|
@ -1,14 +1,24 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type Level int8
|
type Level int8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TraceLevel Level = iota - 1
|
// TraceLevel level. Designates finer-grained informational events than the Debug.
|
||||||
|
TraceLevel Level = iota - 2
|
||||||
|
// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
|
||||||
DebugLevel
|
DebugLevel
|
||||||
|
// InfoLevel is the default logging priority.
|
||||||
|
// General operational entries about what's going on inside the application.
|
||||||
InfoLevel
|
InfoLevel
|
||||||
|
// WarnLevel level. Non-critical entries that deserve eyes.
|
||||||
WarnLevel
|
WarnLevel
|
||||||
|
// ErrorLevel level. Logs. Used for errors that should definitely be noted.
|
||||||
ErrorLevel
|
ErrorLevel
|
||||||
|
// PanicLevel level, logs the message and then panics.
|
||||||
PanicLevel
|
PanicLevel
|
||||||
|
// FatalLevel level. Logs and then calls `logger.Exit(1)`. highest level of severity.
|
||||||
FatalLevel
|
FatalLevel
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,10 +34,37 @@ func (l Level) String() string {
|
|||||||
return "warn"
|
return "warn"
|
||||||
case ErrorLevel:
|
case ErrorLevel:
|
||||||
return "error"
|
return "error"
|
||||||
case FatalLevel:
|
|
||||||
return "fatal"
|
|
||||||
case PanicLevel:
|
case PanicLevel:
|
||||||
return "panic"
|
return "panic"
|
||||||
|
case FatalLevel:
|
||||||
|
return "fatal"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enabled returns true if the given level is at or above this level.
|
||||||
|
func (l Level) Enabled(lvl Level) bool {
|
||||||
|
return lvl >= l
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLevel converts a level string into a logger Level value.
|
||||||
|
// returns an error if the input string does not match known values.
|
||||||
|
func GetLevel(levelStr string) (Level, error) {
|
||||||
|
switch levelStr {
|
||||||
|
case TraceLevel.String():
|
||||||
|
return TraceLevel, nil
|
||||||
|
case DebugLevel.String():
|
||||||
|
return DebugLevel, nil
|
||||||
|
case InfoLevel.String():
|
||||||
|
return InfoLevel, nil
|
||||||
|
case WarnLevel.String():
|
||||||
|
return WarnLevel, nil
|
||||||
|
case ErrorLevel.String():
|
||||||
|
return ErrorLevel, nil
|
||||||
|
case PanicLevel.String():
|
||||||
|
return PanicLevel, nil
|
||||||
|
case FatalLevel.String():
|
||||||
|
return FatalLevel, nil
|
||||||
|
}
|
||||||
|
return InfoLevel, fmt.Errorf("Unknown Level String: '%s', defaulting to NoLevel", levelStr)
|
||||||
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// Package log provides a log interface
|
// Package log provides a log interface
|
||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
var (
|
||||||
"fmt"
|
// Default logger
|
||||||
"sync"
|
DefaultLogger Logger = NewLogger()
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logger is a generic logging interface
|
// Logger is a generic logging interface
|
||||||
@ -24,45 +24,32 @@ type Logger interface {
|
|||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
func Init(opts ...Option) error {
|
||||||
mtx sync.Mutex
|
return DefaultLogger.Init(opts...)
|
||||||
loggerMap = map[string]Logger{}
|
|
||||||
)
|
|
||||||
|
|
||||||
func Register(logger Logger) {
|
|
||||||
mtx.Lock()
|
|
||||||
defer mtx.Unlock()
|
|
||||||
|
|
||||||
loggerMap[logger.String()] = logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLogger(name string) (Logger, error) {
|
func Error(err error) Logger {
|
||||||
l := loggerMap[name]
|
return DefaultLogger.Error(err)
|
||||||
if l == nil {
|
|
||||||
return nil, fmt.Errorf("no such name logger found %s", name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return l, nil
|
func Fields(fields map[string]interface{}) Logger {
|
||||||
|
return DefaultLogger.Fields(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLevel converts a level string into a logger Level value.
|
func Log(level Level, v ...interface{}) {
|
||||||
// returns an error if the input string does not match known values.
|
DefaultLogger.Log(level, v...)
|
||||||
func GetLevel(levelStr string) (Level, error) {
|
|
||||||
switch levelStr {
|
|
||||||
case TraceLevel.String():
|
|
||||||
return TraceLevel, nil
|
|
||||||
case DebugLevel.String():
|
|
||||||
return DebugLevel, nil
|
|
||||||
case InfoLevel.String():
|
|
||||||
return InfoLevel, nil
|
|
||||||
case WarnLevel.String():
|
|
||||||
return WarnLevel, nil
|
|
||||||
case ErrorLevel.String():
|
|
||||||
return ErrorLevel, nil
|
|
||||||
case FatalLevel.String():
|
|
||||||
return FatalLevel, nil
|
|
||||||
case PanicLevel.String():
|
|
||||||
return PanicLevel, nil
|
|
||||||
}
|
}
|
||||||
return InfoLevel, fmt.Errorf("Unknown Level String: '%s', defaulting to NoLevel", levelStr)
|
|
||||||
|
func Logf(level Level, format string, v ...interface{}) {
|
||||||
|
DefaultLogger.Logf(level, format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetGlobalLevel(lvl Level) {
|
||||||
|
if err := Init(WithLevel(lvl)); err != nil {
|
||||||
|
print(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func String() string {
|
||||||
|
return DefaultLogger.String()
|
||||||
}
|
}
|
||||||
|
@ -2,30 +2,48 @@ package logger
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Option for load profiles maybe
|
|
||||||
// eg. yml
|
|
||||||
// micro:
|
|
||||||
// logger:
|
|
||||||
// name:
|
|
||||||
// dialect: zap/default/logrus
|
|
||||||
// zap:
|
|
||||||
// xxx:
|
|
||||||
// logrus:
|
|
||||||
// xxx:
|
|
||||||
type Option func(*Options)
|
type Option func(*Options)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
// The Log Level
|
// The logging level the logger should log at. default is `InfoLevel`
|
||||||
Level Level
|
Level Level
|
||||||
// Other opts
|
// fields to always be logged
|
||||||
|
Fields map[string]interface{}
|
||||||
|
// It's common to set this to a file, or leave it default which is `os.Stderr`
|
||||||
|
Out io.Writer
|
||||||
|
// Alternative options
|
||||||
Context context.Context
|
Context context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithLevel sets the log level
|
// WithFields set default fields for the logger
|
||||||
func WithLevel(l Level) Option {
|
func WithFields(fields map[string]interface{}) Option {
|
||||||
|
return func(args *Options) {
|
||||||
|
args.Fields = fields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLevel set default level for the logger
|
||||||
|
func WithLevel(level Level) Option {
|
||||||
|
return func(args *Options) {
|
||||||
|
args.Level = level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOutput set default output writer for the logger
|
||||||
|
func WithOutput(out io.Writer) Option {
|
||||||
|
return func(args *Options) {
|
||||||
|
args.Out = out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetOption(k, v interface{}) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.Level = l
|
if o.Context == nil {
|
||||||
|
o.Context = context.Background()
|
||||||
|
}
|
||||||
|
o.Context = context.WithValue(o.Context, k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user