micro/logger/default.go
Vasiliy Tolstov 89ba602e17
logger fixes and improvements (#1285)
* fix helper fields
* add metadata output for default logger

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2020-03-03 11:07:37 +03:00

141 lines
2.7 KiB
Go

package logger
import (
"context"
"fmt"
"os"
"sort"
"sync"
"time"
dlog "github.com/micro/go-micro/v2/debug/log"
)
type defaultLogger struct {
sync.RWMutex
opts Options
}
// 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.Lock()
l.opts.Fields = copyFields(fields)
l.Unlock()
return l
}
func copyFields(src map[string]interface{}) map[string]interface{} {
dst := make(map[string]interface{}, len(src))
for k, v := range src {
dst[k] = v
}
return dst
}
func (l *defaultLogger) Log(level Level, v ...interface{}) {
// TODO decide does we need to write message if log level not used?
if !l.opts.Level.Enabled(level) {
return
}
l.RLock()
fields := copyFields(l.opts.Fields)
l.RUnlock()
fields["level"] = level.String()
rec := dlog.Record{
Timestamp: time.Now(),
Message: fmt.Sprint(v...),
Metadata: make(map[string]string, len(fields)),
}
keys := make([]string, 0, len(fields))
for k, v := range fields {
keys = append(keys, k)
rec.Metadata[k] = fmt.Sprintf("%v", v)
}
sort.Strings(keys)
metadata := ""
for _, k := range keys {
metadata += fmt.Sprintf(" %s=%v", k, fields[k])
}
dlog.DefaultLog.Write(rec)
t := rec.Timestamp.Format("2006-01-02 15:04:05")
fmt.Printf("%s %s %v\n", t, metadata, rec.Message)
}
func (l *defaultLogger) Logf(level Level, format string, v ...interface{}) {
// TODO decide does we need to write message if log level not used?
if level < l.opts.Level {
return
}
l.RLock()
fields := copyFields(l.opts.Fields)
l.RUnlock()
fields["level"] = level.String()
rec := dlog.Record{
Timestamp: time.Now(),
Message: fmt.Sprintf(format, v...),
Metadata: make(map[string]string, len(fields)),
}
keys := make([]string, 0, len(fields))
for k, v := range fields {
keys = append(keys, k)
rec.Metadata[k] = fmt.Sprintf("%v", v)
}
sort.Strings(keys)
metadata := ""
for _, k := range keys {
metadata += fmt.Sprintf(" %s=%v", k, fields[k])
}
dlog.DefaultLog.Write(rec)
t := rec.Timestamp.Format("2006-01-02 15:04:05")
fmt.Printf("%s %s %v\n", t, metadata, rec.Message)
}
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}
if err := l.Init(opts...); err != nil {
l.Log(FatalLevel, err)
}
return l
}