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 } }