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
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:
-
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
-
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