如何在所有执行上下文的播放框架日志中记录请求 ID
Posted
技术标签:
【中文标题】如何在所有执行上下文的播放框架日志中记录请求 ID【英文标题】:How to log request Id in play framework log across all execution context 【发布时间】:2016-07-27 19:49:39 【问题描述】:我们有一个庞大的遗留代码,其中包含具有同步和异步操作的复杂流程。因此,我们需要在所有日志消息中记录特定请求的唯一 ID,其中执行的操作在不同的线程中运行,并且线程处于多个执行上下文中。
我尝试使用 MDC 并在 logger.xml 中指定 -%Xreq_id 以及使用自定义 akka 调度程序在下面提到的博客中给出的解决方案,但它不能在多个执行上下文中工作,而且它也不能可靠地工作在单个执行上下文中,有时它返回 req_id null。 (http://yanns.github.io/blog/2014/05/04/slf4j-mapped-diagnostic-context-mdc-with-play-framework/)
由于复杂和庞大的代码库,不可能在每个函数调用中传递请求 ID。有什么方法可以实现这一点,而且改动最少?我们也需要播放框架生成的日志中的请求 ID。
【问题讨论】:
【参考方案1】:我也有同样的需要,为了调试目的记录一些跟踪令牌。 Kamon 库已经有这个功能http://kamon.io/integrations/logback/trace-token-converter/.
在我的 Global.java 中:我在 onStart() 中执行 Kamon.start()
并在 onRequest() 中维护上下文。还要在日志模式中使用traceToken
。
public Action onRequest(Http.Request request, Method actionMethod)
TraceContext tx = Kamon.tracer().newContext("reqc", new Some<>(Utils.randStr(8)));
Tracer.setCurrentContext(tx);
Logger.info("Request: " + request.toString());
Action x = super.onRequest(request, actionMethod);
tx.finish();
return x;
【讨论】:
但 onRequest() 不适用于 Play 中的所有执行上下文。根据我的理解,我说的对吗?onRequest()
仅在发出请求时可用。同样,在所有其他上下文中,您必须创建并完成 TraceContext
。【参考方案2】:
我们通过移动到单个执行器上下文解决了这个问题,play 2.5 也建议这样做。在这种情况下,mdc 上下文将起作用。
【讨论】:
所以你解决了,但是怎么解决的?因为这只是评论而不是解决方案! 在 application.conf 中你必须定义了不同的执行上下文。只是不要使用一个,我现在没有conf文件的副本。【参考方案3】:您应该可以使用marker context 来完成这项工作。来自示例:
trait RequestMarkerContext
// Adding 'implicit request' enables implicit conversion chaining
// See http://docs.scala-lang.org/tutorials/FAQ/chaining-implicits.html
implicit def requestHeaderToMarkerContext(implicit request: RequestHeader): MarkerContext =
import net.logstash.logback.marker.LogstashMarker
import net.logstash.logback.marker.Markers._
val requestMarkers: LogstashMarker = append("host", request.host)
.and(append("path", request.path))
MarkerContext(requestMarkers)
然后
def asyncIndex = Action.async implicit request =>
Future
methodInOtherExecutionContext() // implicit conversion here
(otherExecutionContext)
def methodInOtherExecutionContext()(implicit mc: MarkerContext): Result =
logger.debug("index: ") // same as above
Ok("testing")
【讨论】:
以上是关于如何在所有执行上下文的播放框架日志中记录请求 ID的主要内容,如果未能解决你的问题,请参考以下文章
Java 基础学习总结(203)—— 生成唯一 ID 打印日志记录最佳实践
Java 基础学习总结(203)—— 生成唯一 ID 打印日志记录最佳实践