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 using the LoggingAdapter
LoggingAdapter
of the RequestContext
RequestContext
.
This directive is a combination of logRequest and logResult.
See logRequest for the general description how these directives work.
Example
- Scala
-
source
// different possibilities of using logRequestResult // 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 will only log rejections val rejectionLogger: HttpRequest => RouteResult => Option[LogEntry] = req => { case Rejected(rejections) => Some(LogEntry(s"Request: $req\nwas rejected with rejections:\n$rejections", Logging.DebugLevel)) case _ => None } DebuggingDirectives.logRequestResult(rejectionLogger) // 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" }
- Java
-
source
import static org.apache.pekko.http.javadsl.server.Directives.logRequestResultOptional; // using logRequestResult // handle request to optionally generate a log entry BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>> requestMethodAsInfo = (request, response) -> (response.status().isSuccess()) ? Optional.of( LogEntry.create( request.method().name() + ":" + response.status().intValue(), InfoLevel())) : Optional.empty(); // not a successful response // handle rejections to optionally generate a log entry BiFunction<HttpRequest, List<Rejection>, Optional<LogEntry>> rejectionsAsInfo = (request, rejections) -> (!rejections.isEmpty()) ? Optional.of( LogEntry.create( rejections.stream() .map(Rejection::toString) .collect(Collectors.joining(", ")), InfoLevel())) : Optional.empty(); // no rejections final Route route = get( () -> logRequestResultOptional( requestMethodAsInfo, rejectionsAsInfo, () -> complete("logged"))); // tests: testRoute(route).run(HttpRequest.GET("/")).assertEntity("logged");
Building Advanced Directives
This example will showcase the advanced logging using the DebuggingDirectives
DebuggingDirectives
. The built logResponseTime directive will log the request time (or rejection reason):
- Scala
-
source
def pekkoResponseTimeLoggingFunction( loggingAdapter: LoggingAdapter, requestTimestamp: Long, level: LogLevel = Logging.InfoLevel)(req: HttpRequest)(res: RouteResult): 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 pekkoResponseTimeLoggingFunction(log, requestTimestamp) _ } val logResponseTime = DebuggingDirectives.logRequestResult(LoggingMagnet(printResponseTime)) Get("/") ~> logResponseTime(complete("logged")) ~> check { responseAs[String] shouldEqual "logged" } - Java
-
source
// using logRequestResultOptional for generating Response Time // handle request to optionally generate a log entry BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>> requestMethodAsInfo() { Long requestTime = System.nanoTime(); return new BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>>() { @Override public Optional<LogEntry> apply(HttpRequest request, HttpResponse response) { return printResponseTime(request, response, requestTime); } }; } @Test public void testLogRequestResultWithResponseTime() { // handle rejections to optionally generate a log entry BiFunction<HttpRequest, List<Rejection>, Optional<LogEntry>> rejectionsAsInfo = (request, rejections) -> (!rejections.isEmpty()) ? Optional.of( LogEntry.create( rejections.stream() .map(Rejection::toString) .collect(Collectors.joining(", ")), InfoLevel())) : Optional.empty(); // no rejections final Route route = get( () -> logRequestResultOptional( requestMethodAsInfo(), rejectionsAsInfo, () -> complete("logged"))); // tests: testRoute(route).run(HttpRequest.GET("/")).assertEntity("logged");
1.1.0