How to do request / thread context?

This may be a stupid question but here goes.

We have a few variables which get initialized/derived from the request which we would like to have access to the entire lifespan of the request-handling (Most notably a correlation-id which will be passed along to other api’s as well).

In other libraries we used java.lang.ThreadLocal and log4j ThreadContext to have it readily loggable, but I just discovered that didn’t really work as i expected with tapir+http4s.

How would i go about achieving the same result with tapir+http4s without passing it along in every function signature?

Best case scenario is that i can extract it in a middleware and set it someplace globally, but every bit of help is appreciated :smile:

Hi Jonas!

The fact that ThreadLocal doesn’t work in this case is a more general issue, not directly caused by Tapir or http4s. If you’re using http4s then probably your underlying effect is a cats.effect.IO, and this library brings its own sophisticated threading model based on Fibers, which cross thread boundary, see Thread Model · Cats Effect. Basically one request handling flow is no longer an operation happening on one JVM thread where you could store data. The IO effect uses a concept of Fibers, which represent a single flow, but may jump between threads. For example, each time you flatMap a IO with another IO you must assume that the second one may run on another thread.
Thus, more sophisticated techniques are needed to have a fiber-local memory for correllation Id and other contextual data. Here are a few possibilities:

  1. Leverage IOLocal (IOLocal · Cats Effect), here’s an example of using it for correllationId in Bootzooka, our showcase project using Tapir and http4s bootzooka/CorrelationId.scala at 28b796750a61b6914334a09991aacf5d0db62b6a · softwaremill/bootzooka · GitHub

  2. Explore trace4cats GitHub - trace4cats/trace4cats-sttp: Integration for Trace4Cats and Sttp/Tapir

1 Like

Thanks, that helped me understand quite a bit more!

Our codebase hasn’t fully embraced the cats.effect.IO mindset yet (and many endpoints simply pretend to be pure and not use IO at all).

I understand that its not really optimal, but its an old codebase that is being improved upon little by little (Just now being refactored from scalatra->tapir).

That combined with the fact that we would like to log a correlation-id every time we log something (much like you did in Bootzooka) complicates things and makes the rewrite quite a bit bigger.

Not the thing I’m most excited to learn about, but I guess there isn’t really a quickfix for us here, so I guess we’ll have to rewrite everywhere we do logging :thinking: