spray.io logRequestResponse到专用的日志文件

时间:2015-10-22 11:49:16

标签: scala akka spray

我正在使用REST框架的REST api和调试指令logRequestResponse。我想创建一个审计日志 - 专用日志,其中包含有关访问此api请求/答复的信息。为此,我使用logRequestResponse,但我很难将这些日志矩形分离为专用日志。我可以提供一个标记,但不能提供记录器,因为它是主要的,所以不能使用loogger。 特质RestApi扩展指令{   this:具有Core =>

的ServiceActors

//我们为Futures and Scheduler使用封闭的ActorContext或ActorSystem的调度程序   private implicit val _ = system.dispatcher   隐式val超时=超时(30.seconds)

  val route: Route = 
    logRequestResponse("REST API", Logging.InfoLevel){
        new DataServiceApi(dataService).route ~
        new AnalyticsServiceApi(analyticsService).route
    }

2015-10-22 12:59:45,599 [INFO ] [BackEndServices-akka.actor.default-dispatcher-16] [akka.actor.ActorSystemImpl]ActorSystem(BackEndServices) - REST API: Response for
  Request : HttpRequest(GET,http://localhost:8080/service/analytics/ ...
  Response: HttpResponse(200 OK,HttpEntity(application/json; charset=UTF-8, ...

有一种简单的方法可以实现吗?

1 个答案:

答案 0 :(得分:3)

如果你深入研究一下实现,你会发现logRequestResponse指令最终使用了Akka提供的日志工具。因此,如果您尚未查看Akka日志文档,请务必查看。

Akka 2.4.0 Logging

如果要将请求和响应记录到单独的日志文件中,则最好利用您正在使用的任何日志记录库。

让我们假设你正在使用Logback,因为Akka为SLF4J提供了很好的支持,团队推荐它。

要开始将请求和响应记录到单独的日志文件中,您需要:

  1. 配置您的Spray / Akka应用程序以使用Logback
  2. 在logback.xml中配置单独的记录器和追加器
  3. 对于第1步,请执行以下操作(这完全在Akka文档中):

    1. 还将akka-slf4j jar与您的项目打包
    2. 将此配置添加到application.conf
    3. application.conf

      akka {
        loggers = ["akka.event.slf4j.Slf4jLogger"]
        loglevel = "DEBUG"
      }
      

      对于第2步,您的logback.xml应该有2个appender - 一个用于记录所有内容的控制台,另一个用于捕获logRequestResponse指令生成的日志。像你在下面看到的东西:

      logback.xml

      <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
          <target>System.out</target>
          <encoder>
              <pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
          </encoder>
      </appender>
      
      <appender name="ACCESS" class="ch.qos.logback.core.FileAppender">
          <file>access.log</file>
          <encoder>
              <pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
          </encoder>
      </appender>
      
      
      <root>
          <appender-ref ref="CONSOLE"/>
      </root>
      
      <logger name="akka.actor.RepointableActorRef" level="INFO">
          <appender-ref ref="ACCESS" />
      </logger>
      
      <logger name="akka" level="INFO"/>
      

      这应该记录您的请求和对access.log文件的响应。

      但有一点不是特别好,我们的记录器总是输出为“akka.actor.RepointableActorRef”。而且你最终可能会得到你不关心写入该文件的其他日志语句。

      这是Spray的LoggingContext实现的结果,它最终通过将ActorRef类型传递给LoggingAdapter构造函数来构造LoggingAdapter。

      Logging(context.system.eventStream, context.self)
      

      我们可以通过在您的路线中混合实现我们自己的LoggingMagnet并使用我们构建的LoggingAdapter(而不是Spray库)来解决这个问题。

      这样的事情:

      import akka.actor.Actor
      import akka.event.Logging
      import spray.http.HttpRequest
      import spray.routing.directives.LoggingMagnet
      
      
      trait AccessLogger { this: Actor =>
      
        val accessLogger: LoggingMagnet[HttpRequest => Any => Unit] = LoggingMagnet {
          request => response =>
            val accessLogger = Logging(context.system.eventStream, "com.my.AccessLogger")
            accessLogger.info("Request: " + request + "\n Response: " + response)
        }
      
      }
      

      对于你jaksky,我想你可能会将AccessLogger混合到RestApi

      从log:

      更新logback.xml上的记录器
      <logger name="akka.actor.RepointableActorRef" level="INFO">
          <appender-ref ref="ACCESS" />
      </logger>
      

      ......对此:

      <logger name="com.my.AccessLogger" level="INFO">
          <appender-ref ref="ACCESS" />
      </logger>
      

      然后,您可以将AccessLogger特征中的accessLogger传递给logRequestResponse指令

      logRequestResponse(accessLogger){
        //... rest of route ...
      }
      

      应用这些更改后,您的所有请求和响应都应记录到com.my.AccessLogger记录器中,而该记录器又配置为按照ACCESS appender中的配置写入其自己的文件。

      如果您对使用Logback或Akka进行日志记录不感兴趣,可以始终使用类似的方法,但只提供AccessLogger的不同实现。