-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using global logger fails to bind values causing incorrect context values #3417
Comments
提供一下最小复现呗?最小复现不是指几张截图,而是一个能完全运行的例子。你可以像这样操作:
比如说这就是一个最小复现: package main
import (
"context"
"github.com/go-kratos/kratos/v2/log"
)
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, traceIdKey{}, "123456")
global := log.GetLogger()
logger := log.WithContext(ctx, global)
// logger = log.With(logger, "traceId", TraceIdValue()) // 看后面的说明
helper := log.NewHelper(logger)
helper.Infow("msg", "用户登录", "user", "张三")
// 期望输出
// INFO traceId=123456 msg=用户登录 user=张三
// 实际输出
// INFO msg=用户登录 user=张三
}
type traceIdKey struct{}
// 看后面的说明
func TraceIdValue() log.Valuer {
return func(ctx context.Context) any {
return ctx.Value(traceIdKey{})
}
} 这只是个例子。如果这个例子刚好能反映你的情况的话。那么问题就简单了。log 库并没有“能把 context 里所有 value 都打印出来” 的能力。想要从 context 里拿数据打印需要自己实现 logger 或者 valuer。比如例子中的 |
@kvii package main
import (
"context"
"github.com/go-kratos/kratos/v2/log"
)
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, traceIdKey{}, "123456")
logger := log.DefaultLogger
newLogger := log.With(logger, "traceId", TraceIdValue())
log.SetLogger(newLogger) // setting logger with valuer as global
helper := log.NewHelper(newLogger)
helper.WithContext(ctx).Info("This prints the traceID correctly")
globalLogger := log.NewHelper(log.GetLogger()) // getting the global logger
globalLogger.WithContext(ctx).Info("This does not print the traceID")
// INFO traceId=123456 msg=This prints the traceID correctly
// INFO traceId=<nil> msg=This does not print the traceID
}
type traceIdKey struct{}
func TraceIdValue() log.Valuer {
return func(ctx context.Context) any {
return ctx.Value(traceIdKey{})
}
} |
中文省流:因为 English version: package main
import (
"context"
"os"
"github.com/go-kratos/kratos/v2/log"
)
func main() {
l1 := log.NewStdLogger(os.Stderr) // *log.stdLogger
l2 := log.With(l1, "traceId", traceIdValuer) // *log.logger ctx=Background
log.SetLogger(l2) // log.global.Logger = l2
l3 := log.GetLogger() // log.global not l2 *log.loggerAppliance
ctx := context.TODO()
ctx = context.WithValue(ctx, traceIdKey{}, "123456")
// log.WithContext(ctx,l) only "merge" ctx when l is a *log.logger.
// and l3 is not.
l4 := log.WithContext(ctx, l3) // *log.logger (not l2) ctx=ctx
l4.Log(log.LevelInfo, "msg", "m")
// want:
// INFO traceId=123456 msg=m
// got:
// INFO traceId=<nil> msg=m
// solution: Let log.global be a place that only stores values, rather than a Logger.
}
type traceIdKey struct{}
var traceIdValuer log.Valuer = func(ctx context.Context) any {
return ctx.Value(traceIdKey{})
} Currently Lines 10 to 39 in 908e625
|
|
What happened:
Using a global logger fails to output correct values from the context. It instead creates a background context and fills data with empty values
What you expected to happen:
How to reproduce it (as minimally and precisely as possible):
Because the global logger is of type
loggerAppliance
, usingWithContext
causes it to return a new instance without prefix and kvs. This causes the code to not bind values and causes the downstream logger to not have contextAnything else we need to know?:
Environment:
kratos -v
):go version
):cat /etc/os-release
):The text was updated successfully, but these errors were encountered: