我有一个Spring-Boot应用程序,其中也正在启动gRPC服务器/服务。 servlet和gRPC代码都将请求发送到公共对象以处理该请求。当请求到达时,我想更新日志以显示唯一的“ ID”,以便我可以通过系统跟踪请求。
在Spring端,我设置了一个“过滤器”,用于更新日志记录MDC,以将一些数据添加到日志请求(see this example)中。 这很好
在gRPC端,我创建了一个'ServerInterceptor'并将其添加到服务中,而拦截器被调用以更新MDC的代码不坚持,因此当请求通过gRPC服务我没有在日志中打印ID。 我意识到这与以下事实有关:我在一个线程中拦截了该调用,而gRPC在另一个线程中将其调度了,我似乎无法弄清楚的是,如何截获该调用调用执行工作的线程或添加MDC信息,以便将其正确传播到执行工作的线程。
我进行了很多搜索,很惊讶没有找到这个问题/答案,我只能假设我的查询技能缺乏:(
我刚接触gRPC,这是我正在编写的第一个拦截器。我尝试了几种不同的方式(通过ServerInterceptors.intercept,BindableService instance.intercept)添加拦截器。
我看过LogNet's Spring Boot gRPC Starter,但是我不确定这是否可以解决问题。
这是我在拦截器类中添加的代码
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(final ServerCall<ReqT, RespT> call, final Metadata headers, final ServerCallHandler<ReqT, RespT> next) {
try {
final String mdcData = String.format("[requestID=%s]",
UUID.randomUUID().toString());
MDC.put(MDC_DATA_KEY, mdcData);
return next.startCall(call, headers);
} finally {
MDC.clear();
}
}
当通过RESTful API发出请求时,我会看到这样的日志输出
2019-04-09 10:19:16.331 [requestID=380e28db-c8da-4e35-a097-4b8c90c006f4] INFO 87100 --- [nio-8080-exec-1] c.c.es.xxx: processing request step 1
2019-04-09 10:19:16.800 [requestID=380e28db-c8da-4e35-a097-4b8c90c006f4] INFO 87100 --- [nio-8080-exec-1] c.c.es.xxx: processing request step 2
2019-04-09 10:19:16.803 [requestID=380e28db-c8da-4e35-a097-4b8c90c006f4] INFO 87100 --- [nio-8080-exec-1] c.c.es.xxx: Processing request step 3
...
当请求通过gRPC服务时,我希望得到类似的输出。
谢谢
答案 0 :(得分:1)
由于没有人回答,因此我不断尝试并为我的 interceptCall 函数提出以下解决方案。我不是100%知道为什么会这样,但是对于我的用例却可以。
private class LogInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(final ServerCall<ReqT, RespT> call,
final Metadata headers,
final ServerCallHandler<ReqT, RespT> next) {
Context context = Context.current();
final String requestId = UUID.randomUUID().toString();
return Contexts.interceptCall(context, call, headers, new ServerCallHandler<ReqT, RespT>() {
@Override
public ServerCall.Listener<ReqT> startCall(ServerCall<ReqT, RespT> call, Metadata headers) {
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(next.startCall(call, headers)) {
/**
* The actual service call happens during onHalfClose().
*/
@Override
public void onHalfClose() {
try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.put("requestID",
UUID.randomUUID().toString())) {
super.onHalfClose();
}
}
};
}
});
}
}
在我的application.properties中,添加了以下内容(我已经拥有了)
logging.pattern.level = [%X]%-5level
'%X'告诉日志记录系统打印所有 CloseableThreadContext 键/值。
希望这可以帮助其他人。