[#21090] Added the improved code for loggingResponsetime and added the link in the docs (#21118)

* [#21090] Added the improved code for loggingResponsetime and added the link in the docs

* [#21090] Added javadocs for logRequestResponseTime

* [#21090] Removed the compilation error caused by the missing imports

* [#21090] Removed the compilation error caused by type

* [#21090] Improved the identation of the code

* [#21090] Improved the identation of the code

* [#21090] Removed the empty line

* [#21090] Refactored the documentation with clear explanations
This commit is contained in:
Shivansh Srivastava 2016-08-05 19:46:14 +05:30 committed by Konrad Malawski
parent d1a9049fa0
commit 25e4586aa0
4 changed files with 119 additions and 23 deletions

View file

@ -16,9 +16,11 @@ import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.server.Route; import akka.http.javadsl.server.Route;
import akka.http.javadsl.server.RequestContext; import akka.http.javadsl.server.RequestContext;
import akka.http.javadsl.testkit.JUnitRouteTest; import akka.http.javadsl.testkit.JUnitRouteTest;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import akka.http.javadsl.model.Uri; import akka.http.javadsl.model.Uri;
import akka.http.javadsl.model.headers.Location; import akka.http.javadsl.model.headers.Location;
import akka.http.javadsl.server.directives.DebuggingDirectives; import akka.http.javadsl.server.directives.DebuggingDirectives;
@ -26,10 +28,13 @@ import akka.http.javadsl.server.directives.RouteDirectives;
import akka.event.Logging; import akka.event.Logging;
import akka.event.Logging.LogLevel; import akka.event.Logging.LogLevel;
import akka.http.javadsl.server.directives.LogEntry; import akka.http.javadsl.server.directives.LogEntry;
import java.util.List; import java.util.List;
import akka.http.scaladsl.server.Rejection; import akka.http.scaladsl.server.Rejection;
import static akka.event.Logging.InfoLevel; import static akka.event.Logging.InfoLevel;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.Optional; import java.util.Optional;
@ -39,18 +44,18 @@ public class DebuggingDirectivesExamplesTest extends JUnitRouteTest {
public void testLogRequest() { public void testLogRequest() {
//#logRequest //#logRequest
// logs request with "get-user" // logs request with "get-user"
final Route routeBasicLogRequest = get(() -> final Route routeBasicLogRequest = get(() ->
logRequest("get-user", () -> complete("logged"))); logRequest("get-user", () -> complete("logged")));
// logs request with "get-user" as Info // logs request with "get-user" as Info
final Route routeBasicLogRequestAsInfo = get(() -> final Route routeBasicLogRequestAsInfo = get(() ->
logRequest("get-user", InfoLevel(), () -> complete("logged"))); logRequest("get-user", InfoLevel(), () -> complete("logged")));
// logs just the request method at info level // logs just the request method at info level
Function<HttpRequest, LogEntry> requestMethodAsInfo = (request) -> Function<HttpRequest, LogEntry> requestMethodAsInfo = (request) ->
LogEntry.create(request.method().name(), InfoLevel()); LogEntry.create(request.method().name(), InfoLevel());
final Route routeUsingFunction = get(() -> final Route routeUsingFunction = get(() ->
logRequest(requestMethodAsInfo, () -> complete("logged"))); logRequest(requestMethodAsInfo, () -> complete("logged")));
// tests: // tests:
@ -63,32 +68,31 @@ public class DebuggingDirectivesExamplesTest extends JUnitRouteTest {
public void testLogRequestResult() { public void testLogRequestResult() {
//#logRequestResult //#logRequestResult
// using logRequestResult // using logRequestResult
// handle request to optionally generate a log entry // handle request to optionally generate a log entry
BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>> requestMethodAsInfo = BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>> requestMethodAsInfo =
(request, response) -> (request, response) ->
(response.status().isSuccess()) ? (response.status().isSuccess()) ?
Optional.of( Optional.of(
LogEntry.create( LogEntry.create(
request.method().name() + ":" + response.status().intValue(), request.method().name() + ":" + response.status().intValue(),
InfoLevel())) InfoLevel()))
: Optional.empty(); // not a successful response : Optional.empty(); // not a successful response
// handle rejections to optionally generate a log entry // handle rejections to optionally generate a log entry
BiFunction<HttpRequest, List<Rejection>, Optional<LogEntry>> rejectionsAsInfo = BiFunction<HttpRequest, List<Rejection>, Optional<LogEntry>> rejectionsAsInfo =
(request, rejections) -> (request, rejections) ->
(!rejections.isEmpty()) ? (!rejections.isEmpty()) ?
Optional.of( Optional.of(
LogEntry.create( LogEntry.create(
rejections rejections
.stream() .stream()
.map(Rejection::toString) .map(Rejection::toString)
.collect(Collectors.joining(", ")), .collect(Collectors.joining(", ")),
InfoLevel())) InfoLevel()))
: Optional.empty(); // no rejections : Optional.empty(); // no rejections
final Route route = get(() -> logRequestResultOptional( final Route route = get(() -> logRequestResultOptional(
requestMethodAsInfo, requestMethodAsInfo,
rejectionsAsInfo, rejectionsAsInfo,
() -> complete("logged"))); () -> complete("logged")));
// tests: // tests:
@ -109,16 +113,16 @@ public class DebuggingDirectivesExamplesTest extends JUnitRouteTest {
// logs the result and the rejections as LogEntry // logs the result and the rejections as LogEntry
Function<HttpResponse, LogEntry> showSuccessAsInfo = (response) -> Function<HttpResponse, LogEntry> showSuccessAsInfo = (response) ->
LogEntry.create(String.format("Response code '%d'", response.status().intValue()), LogEntry.create(String.format("Response code '%d'", response.status().intValue()),
InfoLevel()); InfoLevel());
Function<List<Rejection>, LogEntry> showRejectionAsInfo = (rejections) -> Function<List<Rejection>, LogEntry> showRejectionAsInfo = (rejections) ->
LogEntry.create( LogEntry.create(
rejections rejections
.stream() .stream()
.map(rejection -> rejection.toString()) .map(rejection -> rejection.toString())
.collect(Collectors.joining(", ")), .collect(Collectors.joining(", ")),
InfoLevel()); InfoLevel());
final Route routeUsingFunction = get(() -> final Route routeUsingFunction = get(() ->
logResult(showSuccessAsInfo, showRejectionAsInfo, () -> complete("logged"))); logResult(showSuccessAsInfo, showRejectionAsInfo, () -> complete("logged")));
@ -128,4 +132,50 @@ public class DebuggingDirectivesExamplesTest extends JUnitRouteTest {
//#logResult //#logResult
} }
} @Test
public void testLogRequestResultWithResponseTime() {
//#logRequestResultWithResponseTime
// using logRequestResultOptional for generating Response Time
// handle request to optionally generate a log entry
BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>> requestMethodAsInfo =
(request, response) -> {
Long requestTime = System.nanoTime();
return printResponseTime(request, response, requestTime);
};
// 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");
//#logRequestResult
}
// A function for the logging of Time
public static Optional<LogEntry> printResponseTime(HttpRequest request, HttpResponse response, Long requestTime) {
if (response.status().isSuccess()) {
Long elapsedTime = (requestTime - System.nanoTime()) / 1000000;
return Optional.of(
LogEntry.create(
"Logged Request:" + request.method().name() + ":" + request.getUri() + ":" + response.status() + ":" + elapsedTime,
InfoLevel()));
} else {
return Optional.empty(); //not a successfull response
}
}
}

View file

@ -14,3 +14,10 @@ See :ref:`-logRequest-java-` for the general description how these directives wo
Example Example
------- -------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/DebuggingDirectivesExamplesTest.java#logRequestResult .. includecode:: ../../../../code/docs/http/javadsl/server/directives/DebuggingDirectivesExamplesTest.java#logRequestResult
Longer Example
--------------
This example shows how to log the response time of the request using the Debugging Directive
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/DebuggingDirectivesExamplesTest.java#logRequestResultWithResponseTime

View file

@ -4,9 +4,11 @@
package docs.http.scaladsl.server.directives package docs.http.scaladsl.server.directives
import akka.event.Logging import akka.event.{LoggingAdapter, Logging}
import akka.event.Logging.LogLevel
import akka.http.scaladsl.model.{ HttpRequest, HttpResponse } import akka.http.scaladsl.model.{ HttpRequest, HttpResponse }
import akka.http.scaladsl.server.RouteResult import akka.http.scaladsl.server.RouteResult
import akka.http.scaladsl.server.RouteResult.{Rejected, Complete}
import akka.http.scaladsl.server.directives.{ DebuggingDirectives, LogEntry, LoggingMagnet } import akka.http.scaladsl.server.directives.{ DebuggingDirectives, LogEntry, LoggingMagnet }
import docs.http.scaladsl.server.RoutingSpec import docs.http.scaladsl.server.RoutingSpec
@ -95,4 +97,31 @@ class DebuggingDirectivesExamplesSpec extends RoutingSpec {
responseAs[String] shouldEqual "logged" responseAs[String] shouldEqual "logged"
} }
} }
"logRequestResultWithResponseTime" in {
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"
}
}
} }

View file

@ -30,3 +30,13 @@ Example
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala .. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala
:snippet: logRequestResult :snippet: logRequestResult
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):
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/DebuggingDirectivesExamplesSpec.scala
:snippet: logRequestResultWithResponseTime