How to log request Id in play framework log across all execution context
Asked Answered
L

3

8

We have a huge legacy code with complex flow having sync and async operations. So we need to log an unique id for a specific request in all the log messages, where operations performed are running in different threads and that threads are in multiple execution context.

I tried using MDC and specifying -%X{req_id} in logger.xml and solution given in below mentioned blog by using custom akka dispatcher, but it doesn't works in multiple execution context, and also it does not work reliably in single execution context, where sometimes it returns req_id null. (http://yanns.github.io/blog/2014/05/04/slf4j-mapped-diagnostic-context-mdc-with-play-framework/)

Due to complex and huge code base its not possible to pass request id in every function call. Is there any way we can achieve this, with least changes? We need that request id in logs that are generated by play framework too.

Leninism answered 7/4, 2016 at 5:40 Comment(0)
C
1

You should be able to use a marker context to make this work. From the example:

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)
  }

}

and then

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")
}
Comer answered 1/4, 2020 at 17:53 Comment(0)
O
0

I had the same need, to log some trace token for debugging purpose. Kamon library has this feature already http://kamon.io/integrations/logback/trace-token-converter/.

In my Global.java : I do Kamon.start() in onStart() and maintain the context in onRequest(). Also use the traceToken in logging pattern.

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;
}
Onward answered 9/4, 2016 at 3:42 Comment(2)
but onRequest() is not available across all execution context in Play. According to my understanding, am i right?Leninism
onRequest() is only available when a request is made. Similarly in all other context you have to create and finish TraceContext.Onward
L
0

We solved this by moving to single executor context and play 2.5 also recommends to do so. In this scenario mdc context will work.

Leninism answered 25/3, 2017 at 7:58 Comment(2)
So you solved it, but how? as this just a comment not a solution!Headmistress
in application.conf you must have defined different execution context. Just dont use one, I dont have copy of conf file now.Leninism

© 2022 - 2024 — McMap. All rights reserved.