1
0
mirror of https://github.com/go-kratos/kratos.git synced 2025-01-22 03:38:41 +02:00
kratos/log/log.go
ionling ff105d5bca
fix(log): WithContext() changed the ctx field of the parent log.Filter (#3069)
* fix(log): `WithContext()` changed the ctx field of the parent log.Filter

* test(log): add concurrence test for `WithContext()`

* fix(log): concurrence problem of `Filter`

---------

Co-authored-by: 包子 <baozhecheng@foxmail.com>
2023-11-22 11:35:58 +08:00

66 lines
1.4 KiB
Go

package log
import (
"context"
"log"
)
// DefaultLogger is default logger.
var DefaultLogger = NewStdLogger(log.Writer())
// Logger is a logger interface.
type Logger interface {
Log(level Level, keyvals ...interface{}) error
}
type logger struct {
logger Logger
prefix []interface{}
hasValuer bool
ctx context.Context
}
func (c *logger) Log(level Level, keyvals ...interface{}) error {
kvs := make([]interface{}, 0, len(c.prefix)+len(keyvals))
kvs = append(kvs, c.prefix...)
if c.hasValuer {
bindValues(c.ctx, kvs)
}
kvs = append(kvs, keyvals...)
return c.logger.Log(level, kvs...)
}
// With with logger fields.
func With(l Logger, kv ...interface{}) Logger {
c, ok := l.(*logger)
if !ok {
return &logger{logger: l, prefix: kv, hasValuer: containsValuer(kv), ctx: context.Background()}
}
kvs := make([]interface{}, 0, len(c.prefix)+len(kv))
kvs = append(kvs, c.prefix...)
kvs = append(kvs, kv...)
return &logger{
logger: c.logger,
prefix: kvs,
hasValuer: containsValuer(kvs),
ctx: c.ctx,
}
}
// WithContext returns a shallow copy of l with its context changed
// to ctx. The provided ctx must be non-nil.
func WithContext(ctx context.Context, l Logger) Logger {
switch v := l.(type) {
default:
return &logger{logger: l, ctx: ctx}
case *logger:
lv := *v
lv.ctx = ctx
return &lv
case *Filter:
fv := *v
fv.logger = WithContext(ctx, fv.logger)
return &fv
}
}