logRequestResult

logRequestResult

Signature

def logRequestResult(marker: String)(implicit log: LoggingContext): Directive0
def logRequestResult(marker: String, level: LogLevel)(implicit log: LoggingContext): Directive0
def logRequestResult(show: HttpRequest => RouteResult => Option[LogEntry])(implicit log: LoggingContext): Directive0

The signature shown is simplified, the real signature uses magnets. [1]

[1]See The Magnet Pattern for an explanation of magnet-based overloading.

Description

Logs both, the request and the response.

This directive is a combination of logRequest and logResult.

See logRequest for the general description how these directives work.

Example

// different possibilities of using logRequestResponse

// The first alternatives use an implicitly available LoggingContext for logging
// marks with "get-user", log with debug level, HttpRequest.toString, HttpResponse.toString
DebuggingDirectives.logRequestResult("get-user")

// marks with "get-user", log with info level, HttpRequest.toString, HttpResponse.toString
DebuggingDirectives.logRequestResult(("get-user", Logging.InfoLevel))

// logs just the request method and response status at info level
def requestMethodAndResponseStatusAsInfo(req: HttpRequest): RouteResult => Option[LogEntry] = {
  case RouteResult.Complete(res) => Some(LogEntry(req.method.name + ": " + res.status, Logging.InfoLevel))
  case _                         => None // no log entries for rejections
}
DebuggingDirectives.logRequestResult(requestMethodAndResponseStatusAsInfo _)

// This one doesn't use the implicit LoggingContext but uses `println` for logging
def printRequestMethodAndResponseStatus(req: HttpRequest)(res: RouteResult): Unit =
  println(requestMethodAndResponseStatusAsInfo(req)(res).map(_.obj.toString).getOrElse(""))
val logRequestResultPrintln = DebuggingDirectives.logRequestResult(LoggingMagnet(_ => printRequestMethodAndResponseStatus))

// tests:
Get("/") ~> logRequestResultPrintln(complete("logged")) ~> check {
  responseAs[String] shouldEqual "logged"
}

def akkaResponseTimeLoggingFunction(
  loggingAdapter:   LoggingAdapter,
  requestTimestamp: Long,
  level:            LogLevel       = Logging.InfoLevel)(req: HttpRequest)(res: Any): Unit = {
  val entry = res match {
    case Complete(resp) =>
      val responseTimestamp: Long = System.nanoTime
      val elapsedTime: Long = (responseTimestamp - requestTimestamp) / 1000000
      val loggingString = s"""Logged Request:${req.method}:${req.uri}:${resp.status}:${elapsedTime}"""
      LogEntry(loggingString, level)
    case Rejected(reason) =>
      LogEntry(s"Rejected Reason: ${reason.mkString(",")}", level)
  }
  entry.logTo(loggingAdapter)
}
def printResponseTime(log: LoggingAdapter) = {
  val requestTimestamp = System.nanoTime
  akkaResponseTimeLoggingFunction(log, requestTimestamp)(_)
}

val logResponseTime = DebuggingDirectives.logRequestResult(LoggingMagnet(printResponseTime(_)))

Get("/") ~> logResponseTime(complete("logged")) ~> check {
  responseAs[String] shouldEqual "logged"
}

Building Advanced Directives

This example will showcase the advanced logging using the DebuggingDirectives. The built logResponseTime directive will log the request time (or rejection reason):

def akkaResponseTimeLoggingFunction(
  loggingAdapter:   LoggingAdapter,
  requestTimestamp: Long,
  level:            LogLevel       = Logging.InfoLevel)(req: HttpRequest)(res: Any): Unit = {
  val entry = res match {
    case Complete(resp) =>
      val responseTimestamp: Long = System.nanoTime
      val elapsedTime: Long = (responseTimestamp - requestTimestamp) / 1000000
      val loggingString = s"""Logged Request:${req.method}:${req.uri}:${resp.status}:${elapsedTime}"""
      LogEntry(loggingString, level)
    case Rejected(reason) =>
      LogEntry(s"Rejected Reason: ${reason.mkString(",")}", level)
  }
  entry.logTo(loggingAdapter)
}
def printResponseTime(log: LoggingAdapter) = {
  val requestTimestamp = System.nanoTime
  akkaResponseTimeLoggingFunction(log, requestTimestamp)(_)
}

val logResponseTime = DebuggingDirectives.logRequestResult(LoggingMagnet(printResponseTime(_)))

Get("/") ~> logResponseTime(complete("logged")) ~> check {
  responseAs[String] shouldEqual "logged"
}

Contents