我有一个Spring-Boot应用程序,我也在其中启动一个gRPC服务器/服务。servlet和gRPC代码都将请求发送到一个公共对象来处理请求。当请求进来时,我想更新日志记录以显示唯一的“ID”,这样我就可以通过系统跟踪请求。
在Spring端,我设置了一个“过滤器”,用于更新日志MDC,以便向日志请求添加一些数据(参见本例)。这个很好用
在gRPC方面,我创建了一个“服务器拦截器”并将其添加到服务中,而拦截器被调用时,更新MDC的代码不会坚持,所以当请求通过gRPC服务时,我不会在日志中打印ID。我意识到这与我在一个线程中拦截调用,而它在另一个线程中被gRPC调度的事实有关,我似乎不知道如何在执行工作的线程中拦截调用,或者添加MDC信息,以便将其正确地传播到执行工作的线程。
我做了很多搜索,很惊讶没有发现这个问题,我只能假设我的查询技巧是缺乏的:(
我是gRPC的新手,这是我写的第一个拦截器。我尝试了几种不同的方式添加拦截器(通过ServerInterceptors.intercept、BindableService instance.intercept)。
我看过LogNet的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服务时,我希望得到类似的输出。
谢啦
由于没有人回复,我一直在尝试,并为我的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();
}
}
};
}
});
}
}
在我的申请中。我添加了以下内容(我已经有了)
登录中。图案级别=[%X]-5级别
“%X”告诉日志系统打印所有CloseableThreadContext键/值。
希望这能帮助其他人。
我正在将我的应用程序从JBoss 6 AS迁移到Wildfly 8.2.0 AS。我可以实现按预期创建应用程序日志,但需要独立/日志/服务器。日志文件中也充满了应用程序日志。我正在使用独立的完整ha。xml配置。任何人都可以建议一个选项,禁止将应用程序日志填充到服务器中。日志 以下部分摘自standalone-full-ha.xml:
我有一个Spring启动应用程序设置,包括使用log4j日志记录。在应用程序中,很少有层,如等。目前,我已经在层中包含了ERROR级别的日志。 在上面提到的任何层中使用日志记录是否合适? Log4j具有日志级别,如FATAL、ERROR、WARN、INFO、DEBUG和TRACE。如何识别在Spring应用程序中登录时使用这些级别的情况?
本文向大家介绍如何配置Spring Boot应用程序日志记录?相关面试题,主要包含被问及如何配置Spring Boot应用程序日志记录?时的应答技巧和注意事项,需要的朋友参考一下 Spring Boot附带了对Log4J2,Java Util Logging和Logback的支持。它通常预先配置为控制台输出。可以通过仅在application.properties文件中指定logging.leve
我可以创建一个命名的子记录器,以便该记录器输出的所有日志都用它的名称标记。我可以只在函数/类/任何东西中使用记录器。 但是,如果该代码调用了另一个模块中的函数,该模块仅使用日志模块函数(根记录器的代理)进行日志记录,我如何确保这些日志消息通过相同的记录器(或者至少以相同的方式记录)? 例如: main.py 其他.py 产出: 我希望能够使两个日志行都标记为名称'stuff',我希望能够做到这一点
我们正在使用Spring引导将指标发送到应用程序洞察我们正在使用应用程序洞察日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志。 下面是我们在logj2-spring.xml中使用的附加程序 ** 我们在应用洞察搜索屏幕上看到日志,但是我有几个问题。 > 是否有一种方法可以