Skip to content

Instantly share code, notes, and snippets.

@tindzk
Created September 7, 2021 09:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tindzk/42a69aaf0405aa9d09e325befb7aa70a to your computer and use it in GitHub Desktop.
Save tindzk/42a69aaf0405aa9d09e325befb7aa70a to your computer and use it in GitHub Desktop.
Log request and response bodies with Akka-HTTP and ZIO
import zio.logging.Logging
import zio.ZIO
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.Directives._
import scala.concurrent.{ExecutionContext, Future}
object HttpServer {
def entityAsString(
entity: HttpEntity
)(implicit m: Materializer): Future[String] =
entity.dataBytes
.map(
_.decodeString(entity.contentType.charsetOption.fold("UTF-8")(_.value))
)
.runWith(Sink.head)
def logRequestResult(logger: Logger[String], route: Route)(implicit
m: Materializer,
ex: ExecutionContext
): RequestContext => Future[RouteResult] = {
def logRequest(l: LoggingAdapter)(request: HttpRequest): Unit = {
val entry = entityAsString(request.entity)
.map(data => s"<<< ${request.method.value} ${request.uri}: $data")
entry.foreach { message =>
zio.Runtime.global.unsafeRun(logger.info(message))
}
}
def logResponse(l: LoggingAdapter)(response: RouteResult): Unit = {
val entry = response match {
case Complete(body) =>
entityAsString(body.entity).map(data => s">>> ${body.status}: $data")
case other => Future.successful(s">>> $other")
}
entry.foreach { message =>
zio.Runtime.global.unsafeRun(logger.info(message))
}
}
DebuggingDirectives.logRequest(LoggingMagnet(logRequest))(
DebuggingDirectives.logResult(LoggingMagnet(logResponse))(route)
)
}
val mainRoute = ???
val loggingRoute = logRequestResult(logger, mainRoute)(implicitly[Materializer], ExecutionContext.global)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment