【问题标题】:How can I log a warning when I "halt()" in Scalatra?当我在 Scalatra 中“停止()”时,如何记录警告?
【发布时间】:2018-04-05 16:08:13
【问题描述】:

在我的 Scalatra 路由中,我经常使用 halt() 快速失败:

val user: User = userRepository.getUserById(params("userId"))
    .getOrElse {
        logger.warn(s"Unknown user: $userId")
        halt(404, s"Unknown user: $userId")
    }

如示例所示,我还想在这些情况下记录警告。但我想避免halt() 和记录器之间的代码重复。这样做会更干净:

val user: User = userRepository.getUserById(params("userId"))
    .getOrElse(halt(404, s"Unknown user: $userId"))

以横切方式记录所有“HaltExceptions”的最佳方式是什么?

我考虑过:

1) 在我的路由中覆盖halt() 方法:

override def halt[T](status: Integer, body: T, headers: Map[String, String])(implicit evidence$1: Manifest[T]): Nothing = {
    logger.warn(s"Halting with status $status and message: $body")
    super.halt(status, body, headers)
}

除了奇怪的方法签名之外,我不太喜欢这种方法,因为我可能会错误地调用真正的 halt() 而不是覆盖的方法,例如,如果我在路线外停下来。在这种情况下,不会记录任何警告。

2) 使用trap() 记录所有错误响应:

trap(400 to 600) {
    logger.warn(s"Error returned with status $status and body ${extractBodyInSomeWay()}")
}

但我不确定这是不是最好的方法,特别是因为它向 _statusRoutes 映射添加了 201 条路由(范围内的每个整数都有一个映射......)。我也不知道怎么提取这里的尸体?

3) 在 Jetty 中为特定状态代码启用某种响应日志记录?


最好的方法是什么?我是否正确地接近这个?

【问题讨论】:

    标签: scala scalatra


    【解决方案1】:

    最简单的解决方案是在如下所示的 servlet 过滤器中执行此操作:

    package org.scalatra.example
    
    import javax.servlet._
    import javax.servlet.http.HttpServletResponse
    
    class LoggingFilter extends Filter {
    
      override def init(filterConfig: FilterConfig): Unit = ()
      override def destroy(): Unit = ()
    
      override def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain): Unit = {
        chain.doFilter(request, response)
    
        val status = response.asInstanceOf[HttpServletResponse].getStatus
        if (status >= 400 && status <= 600) {
          // Do logging here!
        }
      }
    }
    

    在您的 Bootstrap 类中注册此过滤器(或者甚至可以在 web.xml 中注册):

    package org.scalatra.example
    
    import org.scalatra._
    import javax.servlet.ServletContext
    
    class ScalatraBootstrap extends LifeCycle {
      override def init(context: ServletContext): Unit = {
        context.addFilter("loggingFilter", new LoggingFilter())
        context.getFilterRegistration("loggingFilter")
          .addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
    
        // mount your servlets or filters
        ...
      }
    }
    

    在我看来,Scalatra 应该提供一种从本质上更容易捕获停止的方法。其实ScalatraBase里面有一个叫renderHaltException的方法,乍一看好像可以通过覆盖这个方法来添加日志: https://github.com/scalatra/scalatra/blob/cec3f75e3484f2233274b1af900f078eb15c35b1/core/src/main/scala/org/scalatra/ScalatraBase.scala#L512

    但是我们实际上不能这样做,因为HaltException 是包私有的,它只能在org.scalatra 包内访问。我想知道HaltException 应该是公开的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-05
      • 2013-10-13
      • 2013-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多