如何在所有执行上下文中的play框架日志中记录请求ID

时间:2016-04-07 05:40:26

标签: java logging playframework playframework-2.0 logback

我们有一个庞大的遗留代码,其中包含具有同步和异步操作的复杂流程。因此,我们需要在所有日志消息中记录特定请求的唯一ID,其中执行的操作在不同的线程中运行,并且线程在多个执行上下文中。

我尝试使用MDC并在logger.xml中指定 - %X {req_id}并使用自定义akka调度程序在下面提到的博客中给出解决方案,但它在多个执行上下文中不起作用,并且它也无法可靠地工作在单个执行上下文中,有时它返回req_id null。 (http://yanns.github.io/blog/2014/05/04/slf4j-mapped-diagnostic-context-mdc-with-play-framework/

由于复杂且庞大的代码库,因此无法在每个函数调用中传递请求ID。我们有什么方法可以实现这一目标,但变化最小?我们在play框架生成的日志中也需要该请求id。

3 个答案:

答案 0 :(得分:0)

我有同样的需要,记录一些跟踪令牌以进行调试。 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;
}

答案 1 :(得分:0)

我们通过转移到单个执行器上下文来解决这个问题,并且播放2.5也建议这样做。在这种情况下,mdc上下文将起作用。

答案 2 :(得分:0)

您应该可以使用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")
}