Scala 3: Using context functions for request context with http4s and log4cats


During studying Scala 3 Context Functions first use case I thought about it, was X-Request-ID, X-Correlation-ID or similar headers identifying request context. So in this post, I wanted to show Context Function usage on an example of implementing wiring request context to logs in a simple application with http4s and log4cats.

Alternative approaches

But first, let’s consider alternative approaches to solving this problem:

  • Monix has Local implementation, which can deal with context propagation for Task and Future.
  • ZIO has FiberRef for context propagation in terms of fiber
  • Cats Effect IO’s recently got Fiber Locals similar to previous solutions

Context function

Dotty’s Context Functions on another hand, allows being independent of the underlying effect library because provides the capability to pass request context as a hidden implicit parameter.

Request context propagation

Fortunately, http4s provides RequestId middleware which does half of the job for us: create random UUID and add it as X-Request-ID for into response. We need retrieve it from Request[F] from attributes and pass it through the application.

curl -X GET http://localhost:8080/contextual/test -v
Note: Unnecessary use of -X or --request, GET is already inferred.
* Trying
* Connected to localhost ( port 8080 (#0)
> GET /contextual/test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=UTF-8
< X-Request-ID: f6e8d59e-ddd3-438c-88f6-1136d6838234
< Date: Sun, 30 May 2021 18:21:10 GMT
< Content-Length: 2
* Connection #0 to host localhost left intact
OK* Closing connection 0
21:21:09.972 [io-compute-7] INFO <empty>.ApplicationService - f6e8d59e-ddd3-438c-88f6-1136d6838234 - Received request to handle: test

Pros and cons

From my perspective using context function over other approaches of context propagations (e.g. fiber locals) has next :

Further reading

Related blog posts which you might be interested in and inspired this post: