Adding MDC logging to akka

I’ve mentioned before, but I’m working heavily in a project that is leveraging akka. I am really enjoying the message passing model and so far things are great, but tying in an MDC for the SLFJ logging context proved complicated. I had played with the custom executor model described here but hadn’t attempted the akka custom dispatcher.

I was thinking that a custom dispatcher would work great to pass along the MDC since then you’d never have to think about it, but unfortunately I couldn’t get it to work. Akka kept failing to instantiate the dispatcher. I was also worried about configuration data and possible tuning that you might lose giving akka your own dispatcher configurator.

So, given that I wasn’t quite sure what to do. What I ended up with however was a little extra work but turned out well. I went with an augmented dispatcher/subscriber model. Basically for every event that I send out I wrap it in a PersistentableMessage which traps the fields of the MDC that I care about, and then on any actor I have them subclass a custom logging base class that pops out the persistent message container, sets the MDC, and gives the actor the underlying message.

For my project we’re tracking everything with what we call a CorrelationId which is just a UUID.

This lets me pass in anything that implements a CorrelationIdGetter and if it happens to also be a persisted message, pop out the inner message.

Sending out messages

Now the big issue here is to make sure that we are consistent in publishing messages. This means using routers, broadcasts, etc, all have to make sure to push out a message wrapped in a persistent container. To help make that easier I created a few augmented akka publisher classes. Below is a class with static methods (to make it easy to import) that wrap an actor ref or a router.

Conclusion

And now all I need to do is to wrap a default actor or router give to me by akka. From here on out all messages are auto wrapped and my MDC is properly propagated. While I would have liked to not rely on convention this way, at least I made it simple once you’ve made the right types.