kratos 自定义handler func 没有请求日志的问题及解决
出现的问题 最近在使用 kratos 开发 api 的时候, 由于通过 proto 生成的 server handler 不符合业务的需求, 需要通过自定义 handlerFunc 来定义接口。 在开发中为了程序的可观测性,我使用了 kratos 提供的 logging 中间件。 在使用的过程中, 我发现自定义的 HandlerFunc 的请求日志没有显示, 而 proto 生成的请求正确显示了。 问题的原因 为了找到出现这种情况的原因, 我在官方的 Github 仓库提了个 issue(#1566), 得到了维护人员的解答。 出现这种情况的原因是 自己定义的 handlerFunc 不走 middleware 中间件, 需要自定义 http filter 才能解决。 解决 经过对 http filter 例子的简单研究, 参考了官方的 logging 中间件, 我自己实现了 logging filter. 代码: package middleware import ( "fmt" "net/http" "time" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/transport" ) func Server(logger log.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var ( code int32 reason string kind string operation string ) ctx := r.Context() startTime := time.Now() if info, ok := transport.FromServerContext(ctx); ok { kind = info.Kind().String() operation = info.Operation() } next.ServeHTTP(w, r) if se := errors.FromError(nil); se != nil { code = se.Code reason = se.Reason } level, stack := extractError(nil) _ = log.WithContext(ctx, logger).Log(level, "kind", "server", "component", kind, "operation", operation, "args", extractArgs(r), "code", code, "reason", reason, "stack", stack, "latency", time.Since(startTime).Seconds(), ) }) } } // extractArgs returns the string of the req func extractArgs(req interface{}) string { if stringer, ok := req.(fmt.Stringer); ok { return stringer.String() } return fmt.Sprintf("%+v", req) } // extractError returns the string of the error func extractError(err error) (log.Level, string) { if err != nil { return log.LevelError, fmt.Sprintf("%+v", err) } return log.LevelInfo, "" } 顺利的显示了请求的日志: ...