logger: change logger interface
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
772bde7938
commit
f386bffd37
@ -40,7 +40,6 @@ func (l *defaultLogger) Init(opts ...Option) error {
|
|||||||
l.logFunc = l.opts.Wrappers[i-1].Log(l.logFunc)
|
l.logFunc = l.opts.Wrappers[i-1].Log(l.logFunc)
|
||||||
l.logfFunc = l.opts.Wrappers[i-1].Logf(l.logfFunc)
|
l.logfFunc = l.opts.Wrappers[i-1].Logf(l.logfFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Unlock()
|
l.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -56,26 +55,20 @@ func (l *defaultLogger) V(level Level) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *defaultLogger) Fields(fields map[string]interface{}) Logger {
|
func (l *defaultLogger) Fields(fields ...interface{}) Logger {
|
||||||
nl := &defaultLogger{opts: l.opts, enc: l.enc}
|
nl := &defaultLogger{opts: l.opts, enc: l.enc}
|
||||||
nl.opts.Fields = make(map[string]interface{}, len(l.opts.Fields)+len(fields))
|
if len(fields) == 0 {
|
||||||
l.RLock()
|
return nl
|
||||||
for k, v := range l.opts.Fields {
|
} else if len(fields)%2 != 0 {
|
||||||
nl.opts.Fields[k] = v
|
fields = fields[:len(fields)-1]
|
||||||
}
|
|
||||||
l.RUnlock()
|
|
||||||
|
|
||||||
for k, v := range fields {
|
|
||||||
nl.opts.Fields[k] = v
|
|
||||||
}
|
}
|
||||||
|
nl.opts.Fields = append(l.opts.Fields, fields...)
|
||||||
return nl
|
return nl
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFields(src map[string]interface{}) map[string]interface{} {
|
func copyFields(src []interface{}) []interface{} {
|
||||||
dst := make(map[string]interface{}, len(src))
|
dst := make([]interface{}, len(src))
|
||||||
for k, v := range src {
|
copy(dst, src)
|
||||||
dst[k] = v
|
|
||||||
}
|
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,19 +155,23 @@ func (l *defaultLogger) Log(ctx context.Context, level Level, args ...interface{
|
|||||||
fields := copyFields(l.opts.Fields)
|
fields := copyFields(l.opts.Fields)
|
||||||
l.RUnlock()
|
l.RUnlock()
|
||||||
|
|
||||||
fields["level"] = level.String()
|
fields = append(fields, "level", level.String())
|
||||||
|
|
||||||
if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
|
if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
|
||||||
fields["caller"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
|
fields = append(fields, "caller", fmt.Sprintf("%s:%d", logCallerfilePath(file), line))
|
||||||
}
|
}
|
||||||
|
fields = append(fields, "timestamp", time.Now().Format("2006-01-02 15:04:05"))
|
||||||
|
|
||||||
fields["timestamp"] = time.Now().Format("2006-01-02 15:04:05")
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
fields["msg"] = fmt.Sprint(args...)
|
fields = append(fields, "msg", fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out := make(map[string]interface{}, len(fields)/2)
|
||||||
|
for i := 0; i < len(fields); i += 2 {
|
||||||
|
out[fields[i].(string)] = fields[i+1]
|
||||||
|
}
|
||||||
l.RLock()
|
l.RLock()
|
||||||
_ = l.enc.Encode(fields)
|
_ = l.enc.Encode(out)
|
||||||
l.RUnlock()
|
l.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,30 +184,30 @@ func (l *defaultLogger) Logf(ctx context.Context, level Level, msg string, args
|
|||||||
fields := copyFields(l.opts.Fields)
|
fields := copyFields(l.opts.Fields)
|
||||||
l.RUnlock()
|
l.RUnlock()
|
||||||
|
|
||||||
fields["level"] = level.String()
|
fields = append(fields, "level", level.String())
|
||||||
|
|
||||||
if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
|
if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok {
|
||||||
fields["caller"] = fmt.Sprintf("%s:%d", logCallerfilePath(file), line)
|
fields = append(fields, "caller", fmt.Sprintf("%s:%d", logCallerfilePath(file), line))
|
||||||
}
|
}
|
||||||
|
|
||||||
fields["timestamp"] = time.Now().Format("2006-01-02 15:04:05")
|
fields = append(fields, "timestamp", time.Now().Format("2006-01-02 15:04:05"))
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
fields["msg"] = fmt.Sprintf(msg, args...)
|
fields = append(fields, "msg", fmt.Sprintf(msg, args...))
|
||||||
} else if msg != "" {
|
} else if msg != "" {
|
||||||
fields["msg"] = msg
|
fields = append(fields, "msg", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make(map[string]interface{}, len(fields)/2)
|
||||||
|
for i := 0; i < len(fields); i += 2 {
|
||||||
|
out[fields[i].(string)] = fields[i+1]
|
||||||
}
|
}
|
||||||
l.RLock()
|
l.RLock()
|
||||||
_ = l.enc.Encode(fields)
|
_ = l.enc.Encode(out)
|
||||||
l.RUnlock()
|
l.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *defaultLogger) Options() Options {
|
func (l *defaultLogger) Options() Options {
|
||||||
// not guard against options Context values
|
return l.opts
|
||||||
l.RLock()
|
|
||||||
opts := l.opts
|
|
||||||
opts.Fields = copyFields(l.opts.Fields)
|
|
||||||
l.RUnlock()
|
|
||||||
return opts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLogger builds a new logger based on options
|
// NewLogger builds a new logger based on options
|
||||||
|
@ -20,8 +20,8 @@ type Logger interface {
|
|||||||
V(level Level) bool
|
V(level Level) bool
|
||||||
// The Logger options
|
// The Logger options
|
||||||
Options() Options
|
Options() Options
|
||||||
// Fields set fields to always be logged
|
// Fields set fields to always be logged with keyval pairs
|
||||||
Fields(fields map[string]interface{}) Logger
|
Fields(fields ...interface{}) Logger
|
||||||
// Info level message
|
// Info level message
|
||||||
Info(ctx context.Context, args ...interface{})
|
Info(ctx context.Context, args ...interface{})
|
||||||
// Trace level message
|
// Trace level message
|
||||||
@ -54,6 +54,9 @@ type Logger interface {
|
|||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Field contains keyval pair
|
||||||
|
type Field interface{}
|
||||||
|
|
||||||
// Info writes msg to default logger on info level
|
// Info writes msg to default logger on info level
|
||||||
func Info(ctx context.Context, args ...interface{}) {
|
func Info(ctx context.Context, args ...interface{}) {
|
||||||
DefaultLogger.Info(ctx, args...)
|
DefaultLogger.Info(ctx, args...)
|
||||||
@ -125,6 +128,6 @@ func Init(opts ...Option) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fields create logger with specific fields
|
// Fields create logger with specific fields
|
||||||
func Fields(fields map[string]interface{}) Logger {
|
func Fields(fields ...interface{}) Logger {
|
||||||
return DefaultLogger.Fields(fields)
|
return DefaultLogger.Fields(fields...)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ func TestLogger(t *testing.T) {
|
|||||||
}
|
}
|
||||||
l.Trace(ctx, "trace_msg1")
|
l.Trace(ctx, "trace_msg1")
|
||||||
l.Warn(ctx, "warn_msg1")
|
l.Warn(ctx, "warn_msg1")
|
||||||
l.Fields(map[string]interface{}{"error": "test"}).Info(ctx, "error message")
|
l.Fields("error", "test").Info(ctx, "error message")
|
||||||
l.Warn(ctx, "first", " ", "second")
|
l.Warn(ctx, "first", " ", "second")
|
||||||
if !bytes.Contains(buf.Bytes(), []byte(`"level":"trace","msg":"trace_msg1"`)) {
|
if !bytes.Contains(buf.Bytes(), []byte(`"level":"trace","msg":"trace_msg1"`)) {
|
||||||
t.Fatalf("logger error, buf %s", buf.Bytes())
|
t.Fatalf("logger error, buf %s", buf.Bytes())
|
||||||
|
@ -16,7 +16,7 @@ type Options struct {
|
|||||||
// Context holds exernal options
|
// Context holds exernal options
|
||||||
Context context.Context
|
Context context.Context
|
||||||
// Fields holds additional metadata
|
// Fields holds additional metadata
|
||||||
Fields map[string]interface{}
|
Fields []interface{}
|
||||||
// Name holds the logger name
|
// Name holds the logger name
|
||||||
Name string
|
Name string
|
||||||
// CallerSkipCount number of frmaes to skip
|
// CallerSkipCount number of frmaes to skip
|
||||||
@ -31,7 +31,7 @@ type Options struct {
|
|||||||
func NewOptions(opts ...Option) Options {
|
func NewOptions(opts ...Option) Options {
|
||||||
options := Options{
|
options := Options{
|
||||||
Level: DefaultLevel,
|
Level: DefaultLevel,
|
||||||
Fields: make(map[string]interface{}),
|
Fields: make([]interface{}, 0, 6),
|
||||||
Out: os.Stderr,
|
Out: os.Stderr,
|
||||||
CallerSkipCount: DefaultCallerSkipCount,
|
CallerSkipCount: DefaultCallerSkipCount,
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
@ -43,7 +43,7 @@ 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 ...interface{}) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.Fields = fields
|
o.Fields = fields
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,8 @@ func (w *OmitLogger) Options() Options {
|
|||||||
return w.l.Options()
|
return w.l.Options()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *OmitLogger) Fields(fields map[string]interface{}) Logger {
|
func (w *OmitLogger) Fields(fields ...interface{}) Logger {
|
||||||
return w.l.Fields(fields)
|
return w.l.Fields(fields...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *OmitLogger) Info(ctx context.Context, args ...interface{}) {
|
func (w *OmitLogger) Info(ctx context.Context, args ...interface{}) {
|
||||||
|
Loading…
Reference in New Issue
Block a user