123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- package ctxlog
- import (
- "context"
- "fmt"
- "github.com/ydb-platform/ydb/library/go/core/log"
- )
- type ctxKey struct{}
- // ContextFields returns log.Fields bound with ctx.
- // If no fields are bound, it returns nil.
- func ContextFields(ctx context.Context) []log.Field {
- fs, _ := ctx.Value(ctxKey{}).([]log.Field)
- return fs
- }
- // WithFields returns a new context that is bound with given fields and based
- // on parent ctx.
- func WithFields(ctx context.Context, fields ...log.Field) context.Context {
- if len(fields) == 0 {
- return ctx
- }
- return context.WithValue(ctx, ctxKey{}, mergeFields(ContextFields(ctx), fields))
- }
- // Trace logs at Trace log level using fields both from arguments and ones that
- // are bound to ctx.
- func Trace(ctx context.Context, l log.Logger, msg string, fields ...log.Field) {
- log.AddCallerSkip(l, 1).Trace(msg, mergeFields(ContextFields(ctx), fields)...)
- }
- // Debug logs at Debug log level using fields both from arguments and ones that
- // are bound to ctx.
- func Debug(ctx context.Context, l log.Logger, msg string, fields ...log.Field) {
- log.AddCallerSkip(l, 1).Debug(msg, mergeFields(ContextFields(ctx), fields)...)
- }
- // Info logs at Info log level using fields both from arguments and ones that
- // are bound to ctx.
- func Info(ctx context.Context, l log.Logger, msg string, fields ...log.Field) {
- log.AddCallerSkip(l, 1).Info(msg, mergeFields(ContextFields(ctx), fields)...)
- }
- // Warn logs at Warn log level using fields both from arguments and ones that
- // are bound to ctx.
- func Warn(ctx context.Context, l log.Logger, msg string, fields ...log.Field) {
- log.AddCallerSkip(l, 1).Warn(msg, mergeFields(ContextFields(ctx), fields)...)
- }
- // Error logs at Error log level using fields both from arguments and ones that
- // are bound to ctx.
- func Error(ctx context.Context, l log.Logger, msg string, fields ...log.Field) {
- log.AddCallerSkip(l, 1).Error(msg, mergeFields(ContextFields(ctx), fields)...)
- }
- // Fatal logs at Fatal log level using fields both from arguments and ones that
- // are bound to ctx.
- func Fatal(ctx context.Context, l log.Logger, msg string, fields ...log.Field) {
- log.AddCallerSkip(l, 1).Fatal(msg, mergeFields(ContextFields(ctx), fields)...)
- }
- // Tracef logs at Trace log level using fields that are bound to ctx.
- // The message is formatted using provided arguments.
- func Tracef(ctx context.Context, l log.Logger, format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- log.AddCallerSkip(l, 1).Trace(msg, ContextFields(ctx)...)
- }
- // Debugf logs at Debug log level using fields that are bound to ctx.
- // The message is formatted using provided arguments.
- func Debugf(ctx context.Context, l log.Logger, format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- log.AddCallerSkip(l, 1).Debug(msg, ContextFields(ctx)...)
- }
- // Infof logs at Info log level using fields that are bound to ctx.
- // The message is formatted using provided arguments.
- func Infof(ctx context.Context, l log.Logger, format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- log.AddCallerSkip(l, 1).Info(msg, ContextFields(ctx)...)
- }
- // Warnf logs at Warn log level using fields that are bound to ctx.
- // The message is formatted using provided arguments.
- func Warnf(ctx context.Context, l log.Logger, format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- log.AddCallerSkip(l, 1).Warn(msg, ContextFields(ctx)...)
- }
- // Errorf logs at Error log level using fields that are bound to ctx.
- // The message is formatted using provided arguments.
- func Errorf(ctx context.Context, l log.Logger, format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- log.AddCallerSkip(l, 1).Error(msg, ContextFields(ctx)...)
- }
- // Fatalf logs at Fatal log level using fields that are bound to ctx.
- // The message is formatted using provided arguments.
- func Fatalf(ctx context.Context, l log.Logger, format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- log.AddCallerSkip(l, 1).Fatal(msg, ContextFields(ctx)...)
- }
- func mergeFields(a, b []log.Field) []log.Field {
- if a == nil {
- return b
- }
- if b == nil {
- return a
- }
- // NOTE: just append() here is unsafe. If a caller passed slice of fields
- // followed by ... with capacity greater than length, then simultaneous
- // logging will lead to a data race condition.
- //
- // See https://golang.org/ref/spec#Passing_arguments_to_..._parameters
- c := make([]log.Field, len(a)+len(b))
- n := copy(c, a)
- copy(c[n:], b)
- return c
- }
|