Skip to content

Instantly share code, notes, and snippets.

@padurean
Last active August 29, 2015 14:21
Show Gist options
  • Save padurean/86289cdb3c1c24456f94 to your computer and use it in GitHub Desktop.
Save padurean/86289cdb3c1c24456f94 to your computer and use it in GitHub Desktop.
Play 2 request logging using composed actions
// Actions in controllers will be defined like this:
def create = ComposedAction.async(parse.tolerantJson) { implicit request => ... }
// instead of this:
def create = Action.async(parse.tolerantJson) { implicit request => ... }
package utils.actions
import scala.concurrent.Future
import play.api.mvc.{Action, ActionBuilder, Request, SimpleResult}
object ComposedAction extends ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[SimpleResult]) = block(request)
// More actions can be composed here as in: LoggedAction(AuthenticatedAction(action))
override def composeAction[A](action: Action[A]) = LoggedAction(action)
}
package utils.actions
import scala.concurrent.Future
import play.api.Logger
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.libs.iteratee.{Enumeratee, Iteratee}
import play.api.libs.json.Json
import play.api.mvc._
import spring.config.ApplicationConfiguration._
case class LoggedAction[A](action: Action[A]) extends Action[A] {
private[this] val logger = Logger("utils.actions.LoggedAction")
def apply(request: Request[A]): Future[SimpleResult] = {
val httpMethod = request.method
val start = System.currentTimeMillis()
val futureResult = action(request)
if (logRequests && logRequestsMethods.contains(httpMethod.toUpperCase)) {
futureResult.map { result =>
val duration = System.currentTimeMillis() - start
val uri = request.uri
val reqBody = request.body
val referrer = request.remoteAddress
val requestStr = s"Received Request @$start '$httpMethod $uri' with body '$reqBody'"
logger.info(s"$requestStr from $referrer. HTTP Response code: " +
s"${result.header.status}. Took $duration ms to respond.")
result.withHeaders("Request-Time" -> duration.toString)
}
} else {
futureResult
}
}
lazy val parser = action.parser
}
object LoggedAction extends ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[SimpleResult]) = block(request)
override def composeAction[A](action: Action[A]) = LoggedAction(action)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment