Akka-http记录请求标识符

时间:2017-12-28 00:59:29

标签: scala logging akka akka-http

我现在已经使用 akka-http 了一段时间,到目前为止我通过扩展使用 scala-logging 进行了大部分记录 StrictLogging LazyLogging ,然后调用:

log.info
log.debug
....

这有点好,但很难理解为哪个请求生成了哪些日志。

作为解决方案,我只见过:

  • 添加传递的隐式日志记录上下文(这有点冗长,会强制我将此上下文添加到所有方法调用中)+自定义记录器,将上下文信息添加到记录消息。

  • 使用 MDC 和自定义调度程序;为了实现这种方法,必须使用刚刚弃用的 prepare()调用。

  • 使用 AspectJ

还有其他更简单,更简洁的解决方案吗?可以改变日志库btw ..

1 个答案:

答案 0 :(得分:1)

就个人而言,我会采用隐式上下文方法。我从:

开始
(path("api" / "test") & get) {
  val context = generateContext
  action(requestId)
}

然后我会暗示:

(path("api" / "test") & get) {
  implicit val context = generateContext
  action
}

然后我会将上下文生成一个指令,例如:

val withContext: Directive1[MyContext] = Directive[Tuple1[MyContext]] {
  inner => ctx => inner(Tuple1(generateContext))(ctx)
}

withContext { implicit context =>
  (path("api" / "test") & get) {
     action
   }
}

当然,您必须将上下文作为每个操作的隐式参数。但是,它会比MDC和AspectJ有一些优势 - 它会更容易测试,因为你只需要传递价值。此外,谁说你只需要传递请求ID并用它来记录?上下文也可以传递有关登录用户,其权利以及您可以解决的其他事项的数据,甚至在调用操作和重用内部操作之前使用。

正如你可能猜到的那样,如果你想要这样的能力,这将不起作用。完全删除日志记录在这种情况下,AspectJ会更有意义。

我对MDC最怀疑。如果我理解正确的话,它假设所有逻辑都发生在同一个线程中。如果您使用FuturesTasks,您真的可以保证这样吗?我希望所有日志记录调用最好都发生在同一个线程池中,但不一定是同一个线程。

最重要的是,所有可能的结果都是您已经想到的一些变体,所以问题就在于您的确切用例。