"Transparent"在Grails中将请求/事务ID注入日志消息的方法



我正在寻找一种方法来在我的日志消息中包含某些信息,而不必总是将此信息显式添加到消息本身。

我梦想的场景是,任何日志消息,无论是发生在控制器、服务还是域类中,都将包含一些定义的信息集(例如登录用户的用户名)。这将最好地发生,而程序员根本不用担心它,只需执行log.debug("某些消息")即可自动执行此操作。

这个想法是以JSON格式输出日志,因此上述消息的结构可能如下所示:

{ timestamp: "20130130T12:32", message: "some message", user: "steve", request-id: "245692"... }

我可以创建一个 log4j 布局,为我很好地格式化所有这些,但问题是我首先如何将数据放在那里。

所以我的第一个问题是:Grails内部是否有任何可以用作"request-id"的东西?这背后的想法是为用户启动的任何"事务"提供单个请求 ID。因此,控制器中的日志消息将与因此被调用的域或服务类中的日志消息具有相同的请求 ID。

第二个问题:有没有一种方法可以在用户发起的事务中在层(控制器/服务/域)之间"透明"地移动此类信息?如果需要,我可以在控制器中生成自己的请求ID,在那里我可以获取用户名并将这两个用户名放在地图中。但是,我将如何将该映射传输到任何服务/域类并传输到它们的记录器中,而无需将其作为参数传递(我不想这样做,因为这会乱扔代码)?

任何想法将不胜感激,我应该注意我对Grails相当陌生,所以请温柔;-)

我在 #grails IRC频道上得到了正确的推动。

Log4J(或实际上是SLF4J)具有称为MDC(映射诊断上下文 - http://www.slf4j.org/manual.html#mdc)的东西,它本质上是一个线程本地映射。通过创建过滤器并将我需要的信息添加到 MDC,我能够将此信息包含在该线程中执行的所有日志消息中。

问题仍然存在,是否存在"请求uuid"之类的东西,或者我是否应该使用UUID.randomUUID().toString()生成一个。

例:

添加过滤器以生成和存储requestId

def filters = {
   all(controller:'*', action:'*') {
      before = {
         MDC.put 'requestId', UUID.randomUUID().toString()
      }
   }
}

配置中,在模式中添加%X{requestId}

log4j = {
  appenders {
      console name:'stdout', layout:pattern(conversionPattern: '%d{DATE} %X{requestId} %5p %c{1}:%L - %m%n')

相关内容

最新更新