7

如何以类似于 Apache 记录的方式(即包括 URL 和客户端 IP)记录进入 Play 2 应用程序的所有请求?

4

4 回答 4

10

我想对 Play 2.5.4 做同样的事情。我花了一点时间把这些碎片拼凑在一起,所以我想我会分享我的步骤,希望它能为别人节省时间:

  1. 确保您有访问记录器。在https://www.playframework.com/documentation/2.5.x/SettingsLogger有一个如何配置的示例, 但您可能想要使用这些设置;我用<file>${application.home:-.}/logs/access.log</file>, 和 配置了我的记录器<immediateFlush>true</immediateFlush>

  2. 在根包中创建一个新的 RequestHandler,扩展默认处理程序:

import javax.inject.Inject
import play.api.http._
import play.api.routing._
import play.api.mvc.RequestHeader
import play.api.Logger

/**
 * Implemented to get custom, apache-style logging of requests without dumping the full netty wire.
 */
class RequestHandler @Inject() (router: Router, errorHandler: HttpErrorHandler,
                                configuration: HttpConfiguration, filters: HttpFilters) extends DefaultHttpRequestHandler(
  router, errorHandler, configuration, filters) {

  override def routeRequest(request: RequestHeader) = {
    Logger("access").info(s"Request from ${request.remoteAddress}: ${request}")
    super.routeRequest(request)
  }
}

我来自 Play 2.3,所以我原本打算使用 GlobalSettings,直到找到本指南:https ://www.playframework.com/documentation/2.5.x/GlobalSettings

向任何想要特定于 Play 2.0 答案的人道歉,但鉴于我自己的 2.5 重点搜索将我带到这里,我认为这个答案不会造成太大伤害。

于 2016-07-28T17:33:33.957 回答
7

这就是http过滤器的用途。以下是一些详细示例:http ://www.playframework.com/documentation/2.1.1/ScalaHttpFilters

于 2013-05-24T11:50:45.113 回答
2

在 Play 2.5.x 中,我使用了以下内容

import javax.inject.Inject
import akka.stream.Materializer
import play.api.Logger
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}
import java.util.Calendar
import java.text.SimpleDateFormat

class ApacheLoggingFilter @Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter {

  def apply(nextFilter: RequestHeader => Future[Result])
           (requestHeader: RequestHeader): Future[Result] = {

    nextFilter(requestHeader).map { result =>

      val responseSize =  result.body.contentLength.getOrElse("-")
      Logger("access").info(s"""${requestHeader.remoteAddress} - - [${serverTime}] "${requestHeader}" ${result.header.status} ${responseSize}""")
      result
    }
  }

  private def serverTime = {
    val calendar = Calendar.getInstance()
    val dateFormat = new SimpleDateFormat(
      "dd/MMM/yyyy:HH:mm:ss Z")
    dateFormat.setTimeZone(calendar.getTimeZone)
    dateFormat.format(calendar.getTime())
  }
}

确保正确配置此过滤器 - https://www.playframework.com/documentation/2.5.x/ScalaHttpFilters#Using-filters

于 2017-06-22T17:55:54.617 回答
-1

创建自己的 Action 更加强大和灵活。

object MyAction {
  def apply[A](bodyParser: BodyParser[A])(block: Request[A] => Result): Action[A] = Action(bodyParser) {
    request =>
      // TODO : authentication, cache logics here         

      // time it 
      val start = ...
      // process
      val r = block(request)
      val end = ...

      // log remote address, user agent, time, etc.

      r
  }

  // simply override to use MyAction
  def apply(block: Request[AnyContent] => Result): Action[AnyContent] = this.apply(BodyParsers.parse.anyContent)(block)

  // simply override to use MyAction
  def apply(block: => Result): Action[AnyContent] = this.apply(_ => block)
}

为了在控制器中使用它,只需将 Action 替换为 MyAction

def index = MyAction {
  implicit request =>
     // nothing to be changed here
}
于 2013-05-24T12:55:08.897 回答