设置 MDC 以使用 ServerInterceptor 登录 grpc-java 的正确方法是什么?

What is the proper way to set MDC for logging in grpc-java with ServerInterceptor?

我想使用 log4j2 中的 ThreadContext 来设置 MDC 上下文键,例如 request-iduser-id 以跟踪日志中的请求信息以进行调试。

我写了一个 MdcInterceptor,它执行以下操作:

public class MdcInterceptor implements ServerInterceptor {

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers,
                                                                 ServerCallHandler<ReqT, RespT> next) {
        ThreadContext.put("rid", generateId());
        return next.startCall(call, headers);
    }
}

不幸的是,它不起作用,因为似乎不同的回调可能会从具有不同 ThreadContexts 的服务器执行器的不同线程调用。

我在 https://github.com/grpc/grpc-java/issues/1949#issuecomment-226884288 找到了一些解决方案,其中指出 SimpleForwardingServerCallListener 中的每个回调都应设置 ThreadContext

事实是,在我的情况下,如果可能的话,应该在 MdcInterceptor 之后调用的不同 UserInfoInterceptor 中添加一些附加信息(一些需要令牌验证的身份验证用户信息等)。我应该如何将此信息正确添加到请求范围 ThreadContext

发布的解决方案是唯一可能的变体吗?我在 SimpleForwardingServerCallListener 中将 try-finally 块放在每个超级调用周围,这看起来有点奇怪,更不用说我不应该设置上下文一次,而是在每个回调中设置上下文。

你可以用io.grpc.Context, which handles the propagation of RPC specific information into your callbacks. Before calling any of the events on your ClientCall.Listener (and StreamObserver), the gRPC library will install the correct context. Ray Tsang has made a good example的怎么用API。