我正在使用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, ...
有一种简单的方法可以实现吗?
答案 0 :(得分:3)
如果你深入研究一下实现,你会发现logRequestResponse指令最终使用了Akka提供的日志工具。因此,如果您尚未查看Akka日志文档,请务必查看。
如果要将请求和响应记录到单独的日志文件中,则最好利用您正在使用的任何日志记录库。
让我们假设你正在使用Logback,因为Akka为SLF4J提供了很好的支持,团队推荐它。
要开始将请求和响应记录到单独的日志文件中,您需要:
对于第1步,请执行以下操作(这完全在Akka文档中):
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的不同实现。