JFTR, for now I’m trying to make do with some sugar on top of plain Kleisli
. With this, code may look like this…
class Program[F[_] : CtxLogAware : MonadCancelThrow](client: Client[F]) {
private def parseBody(body: String): F[String] =
if (body.startsWith("!"))
body.tail.pure[F]
else
new IllegalStateException("body parse error").raiseError[F, String]
private def handleResp(status: Int, body: String): F[String] = {
val res =
if (status == 200) {
parseBody(body)
} else
new IllegalStateException("unexpected status").raiseError[F, String]
res
.logOnFail("error handling request")
.addLogCtx("status" -> status)
.addLogCtx("body" -> body)
}
def run(url: String): F[String] =
client
.runRequest(url)
.use((handleResp _).tupled)
.logAround("running request")
.addLogCtx("url" -> url)
}
override def run: IO[Unit] = {
val client: Client[IO] = (_: String) => Resource.eval[IO, (Int, String)]((200, "body").pure[IO])
val prog =
new Program[StructLog[IO, *]](client.mapK(liftToStructLogFunctionK))
.run("http://foo.test/")
.addLogCtx("user" -> "usr-xyz")
prog(Map.empty)
.flatMap(IO.println)
}
Logging output like this:
{"level":"INFO","ctx":{"user":"usr-xyz","url":"http://foo.test/"},"message":"started: running request"}
{"level":"WARN","ctx":{"user":"usr-xyz","url":"http://foo.test/","body":"body","status":200},"message":"error handling request","stack_trace":"java.lang.IllegalStateException: body parse error [...]"}
{"level":"WARN","ctx":{"user":"usr-xyz","url":"http://foo.test/"},"message":"failed: running request","stack_trace":"java.lang.IllegalStateException: body parse error [...]"}
Not sure how happy I am with this…