Merge pull request #16158 from spray/w/15920-DebuggingDirectives

+htp #15920 import DebuggingDirectives from spray
This commit is contained in:
Björn Antonsson 2014-11-03 16:07:12 +01:00
commit 96ba0d07e5
3 changed files with 164 additions and 1 deletions

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.http.server
package directives
import akka.event.LoggingAdapter
import akka.http.util._
class DebuggingDirectivesSpec extends RoutingSpec {
var debugMsg = ""
def resetDebugMsg(): Unit = { debugMsg = "" }
val log = new LoggingAdapter {
def isErrorEnabled = true
def isWarningEnabled = true
def isInfoEnabled = true
def isDebugEnabled = true
def notifyError(message: String): Unit = {}
def notifyError(cause: Throwable, message: String): Unit = {}
def notifyWarning(message: String): Unit = {}
def notifyInfo(message: String): Unit = {}
def notifyDebug(message: String): Unit = { debugMsg += message + '\n' }
}
"The 'logRequest' directive" should {
"produce a proper log message for incoming requests" in {
val route =
withLog(log)(
logRequest("1")(
completeOk))
resetDebugMsg()
Get("/hello") ~> route ~> check {
response shouldEqual Ok
debugMsg shouldEqual "1: HttpRequest(HttpMethod(GET),http://example.com/hello,List(),Strict(none/none,ByteString()),HttpProtocol(HTTP/1.1))\n"
}
}
}
"The 'logResponse' directive" should {
"produce a proper log message for outgoing responses" in {
val route =
withLog(log)(
logResult("2")(
completeOk))
resetDebugMsg()
Get("/hello") ~> route ~> check {
response shouldEqual Ok
debugMsg shouldEqual "2: Complete(HttpResponse(200 OK,List(),Strict(none/none,ByteString()),HttpProtocol(HTTP/1.1)))\n"
}
}
}
"The 'logRequestResponse' directive" should {
"produce proper log messages for outgoing responses, thereby showing the corresponding request" in {
val route =
withLog(log)(
logRequestResult("3")(
completeOk))
resetDebugMsg()
Get("/hello") ~> route ~> check {
response shouldEqual Ok
debugMsg shouldEqual """|3: Response for
| Request : HttpRequest(HttpMethod(GET),http://example.com/hello,List(),Strict(none/none,ByteString()),HttpProtocol(HTTP/1.1))
| Response: Complete(HttpResponse(200 OK,List(),Strict(none/none,ByteString()),HttpProtocol(HTTP/1.1)))
|""".stripMarginWithNewline("\n")
}
}
}
}

View file

@ -13,7 +13,7 @@ trait Directives extends RouteConcatenation
with CacheConditionDirectives
//with ChunkingDirectives
with CookieDirectives
//with DebuggingDirectives
with DebuggingDirectives
with CodingDirectives
with ExecutionDirectives
//with FileAndResourceDirectives

View file

@ -0,0 +1,86 @@
/*
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.http.server
package directives
import akka.event.Logging._
import akka.event.LoggingAdapter
import akka.http.model._
trait DebuggingDirectives {
import BasicDirectives._
def logRequest(magnet: LoggingMagnet[HttpRequest Unit]): Directive0 =
extractRequestContext.flatMap { ctx
magnet.f(ctx.log)(ctx.request)
pass
}
def logResult(magnet: LoggingMagnet[RouteResult Unit]): Directive0 =
extractRequestContext.flatMap { ctx
mapRouteResult { result
magnet.f(ctx.log)(result)
result
}
}
def logRequestResult(magnet: LoggingMagnet[HttpRequest RouteResult Unit]): Directive0 =
extractRequestContext.flatMap { ctx
val logResult = magnet.f(ctx.log)(ctx.request)
mapRouteResult { result
logResult(result)
result
}
}
}
object DebuggingDirectives extends DebuggingDirectives
case class LoggingMagnet[T](f: LoggingAdapter T) // # logging-magnet
object LoggingMagnet {
implicit def forMessageFromMarker[T](marker: String) = // # message-magnets
forMessageFromMarkerAndLevel[T](marker -> DebugLevel)
implicit def forMessageFromMarkerAndLevel[T](markerAndLevel: (String, LogLevel)) = // # message-magnets
forMessageFromFullShow[T] {
val (marker, level) = markerAndLevel
Message LogEntry(Message, marker, level)
}
implicit def forMessageFromShow[T](show: T String) = // # message-magnets
forMessageFromFullShow[T](msg LogEntry(show(msg), DebugLevel))
implicit def forMessageFromFullShow[T](show: T LogEntry): LoggingMagnet[T Unit] = // # message-magnets
LoggingMagnet(log show(_).logTo(log))
implicit def forRequestResponseFromMarker(marker: String) = // # request-response-magnets
forRequestResponseFromMarkerAndLevel(marker -> DebugLevel)
implicit def forRequestResponseFromMarkerAndLevel(markerAndLevel: (String, LogLevel)) = // # request-response-magnets
forRequestResponseFromFullShow {
val (marker, level) = markerAndLevel
request response Some(
LogEntry("Response for\n Request : " + request + "\n Response: " + response, marker, level))
}
implicit def forRequestResponseFromFullShow(show: HttpRequest RouteResult Option[LogEntry]): LoggingMagnet[HttpRequest RouteResult Unit] = // # request-response-magnets
LoggingMagnet { log
request
val showResult = show(request)
result showResult(result).foreach(_.logTo(log))
}
}
case class LogEntry(obj: Any, level: LogLevel = DebugLevel) {
def logTo(log: LoggingAdapter): Unit = {
log.log(level, obj.toString)
}
}
object LogEntry {
def apply(obj: Any, marker: String, level: LogLevel): LogEntry =
LogEntry(if (marker.isEmpty) obj else marker + ": " + obj, level)
}