![](/img/trans.png)
[英]How do I perform an action on server startup in the Scala Play Framework?
[英]How can I perform session based logging in Play Framework
我们当前正在使用Play框架,并且正在使用标准的日志记录机制。 我们实现了一个隐式上下文,以支持将用户名和会话ID传递给所有服务方法。 我们要实现日志记录,使其基于会话。 这需要实现我们自己的记录器。 这适用于我们自己的日志,但是对于基本的异常处理和结果日志,我们该如何做同样的事情。 也许有更好的方法可以使用隐式捕获,或者如何覆盖异常处理日志记录。 本质上,我们希望获得与会话关联的尽可能多的日志消息。
这取决于您要进行反应式样式开发还是标准同步开发:
如果您正在进行反应式开发,则有两种选择:
您仍然可以使用MDC,除非必须使用自定义的执行上下文将有效的MDC值复制到线程,因为理论上每个请求都可以由多个线程处理。 (如此处所述: http : //code.hootsuite.com/logging-contextual-info-in-an-asynchronous-scala-application/ )
另一种选择是我倾向于使用的解决方案(接近于现在的解决方案):您可以创建一个代表MyAppRequest的类。 设置用户名,会话信息以及其他内容。 您可以继续将其作为隐式传递。 但是,您可以创建自己的MyAction类,而不是使用Action.async,如下所示
myAction.async {隐式myRequest => //一些代码}
在myAction内部,您必须捕获所有Exceptions并处理将来的失败,并手动执行错误处理,而不是依赖ErrorHandler。 我经常将myAction注入到我的Controller中,并在其中添加常见的过滤器功能。
缺点是,这只是手动方法。 另外,我还使MyAppRequest拥有一个可记录值的映射,该映射可以在任何地方设置,这意味着它必须是可变的映射。 另外,有时您需要制作多个myAction.async。 优点是,它非常明确,并且在您的控制下没有太多ExecutionContext / ThreadLocal魔术。
下面是一些非常粗略的示例代码,作为手动解决方案的入门:
def logErrorAndRethrow(myrequest:MyRequest, x:Throwable): Nothing = {
//log your error here in the format you like
throw x //you can do this or handle errors how you like
}
class MyRequest {
val attr : mutable.Map[String, String] = new mutable.HashMap[String, String]()
}
//make this a util to inject, or move it into a common parent controller
def myAsync(block: MyRequest => Future[Result] ): Action[AnyContent] = {
val myRequest = new MyRequest()
try {
Action.async(
block(myRequest).recover { case cause => logErrorAndRethrow(myRequest, cause) }
)
} catch {
case x:Throwable =>
logErrorAndRethrow(myRequest, x)
}
}
//the method your Route file refers to
def getStuff = myAsync { request:MyRequest =>
//execute your code here, passing around request as an implicit
Future.successful(Results.Ok)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.