9

As a long time Java EE dev, I've used the MDC (Mapped Diagnostic Context) approach to deal with passing around contextual data relating to a request, e.g. a unique request token for tracking a request across many potential log events that occur during the lifetime of that request.

Given it's reliance on ThreadLocal, it's pretty clear that this approach implodes when using asynchronous techniques.

I'm still in the early days of learning Scala and, more relevant to this question, Akka. I have read plenty of forum postings confirming the incompatibility of Akka and MDC but have not yet uncovered a consistent strategy for mimicking the MDC approach in some way.

Is it simply best to just explicitly pass this sort of data around as part of the messages that get sent between actors? It kind of feels dirty but, at the same time, compatible with the ability to scale effortlessly.

Is there any other way to pass context to an Actor other than directly via messages? Also, has anyone faced this same challenge when using Play 2.0 Async blocks?

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
DrewEaster
  • 3,316
  • 3
  • 35
  • 39
  • 4
    The only way to communicate (pass information) between actors is to send messages and the only piece of information available are the type and contents of the message. You cannot pass information implicitly using some different channel. – Tomasz Nurkiewicz Nov 20 '12 at 07:23
  • @drewzilla, did you ever make any progress on this issue? I'm also curious about tracking request contexts across the lifecycle in play with scala – devshorts Feb 03 '15 at 18:23
  • Related: https://stackoverflow.com/questions/30091356/mdc-mapped-diagnostic-context-logging-in-akka – dskrvk Sep 04 '16 at 20:14

1 Answers1

1

I think you could use ThreadLocal-s declared in a static context, same as executor implicit parameter in this code:

implicit val executor = context.dispatcher
val f = Future[Boolean] {
  someTask()
} andThen { 
  case err if err.isLeft => log.error("Some error: " + err.left.get); false
  case ok if ok.isRight => log.info("Good work: " + ok.right.get); true
}

Each time future submits task to a dispatcher, copy a thread safe context object from one thread into another. So, you need a custom dispatcher - by any means read ThreadLocal, store it internally somewhere inside executor (dispatcher), then submit task that will firstly write into ThreadLocal

idonnie
  • 1,703
  • 12
  • 11