scalaplayframeworkplayframework-2.5

Is there plugins in Play 2.5.x for capturing Request and Response for custom logging purpose?


I'm looking for any possible solutions/plugins to capture request and response that come through Play 2.5.x for making a custom logging.

I've found https://www.playframework.com/documentation/2.5.x/ScalaHttpFilters for Filters, however it cannot get the request body. Is there any way to do that?

The expected result should be all informations in request and response include header and body, so I can construct a custom structure and log it in ElasticSearch.


Solution

  • You can imagine that Playframework works with a request as a pipeline.

    A filter is a right place for logging requests, but, as you found, it has no access to the body. The main reason for this is because on this stage body is not parsed. The filter can reject an inappropriate request just by headers, no need to waste resources to parse the body. That is the main idea of the filters.

    The next stage in a pipeline is an action. If you need to do something with the body of the request, then you need to use an actions composition. Unfortunately, you will need to wrap\replace every action with your composite action.

    Documentation

    https://www.playframework.com/documentation/2.5.x/ScalaActionsComposition

    Example (from the documentation)

    Define logging action:

    def logging[A](action: Action[A])= Action.async(action.parser) { request =>
      Logger.info("Calling action")
      action(request)
    }
    
    object LoggingAction extends ActionBuilder[Request] {
      def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
        block(request)
      }
      override def composeAction[A](action: Action[A]) = new Logging(action)
    }
    

    Use it:

    def index = LoggingAction {
      Ok("Hello World")
    }
    
    def index = Logging {
      Action {
        Ok("Hello World")
      }
    }