我正在寻找一种方法在我的日志消息中包含某些信息,而不必始终将此信息显式添加到消息本身。
我的梦想场景是,任何日志消息,无论是在控制器,服务还是域类中,都会包含一些已定义的信息集(例如登录用户的用户名)。如果没有程序员根本不用担心它就会发生这种情况,只需执行log.debug(“some message”)就可以自动执行此操作。
这个想法是以JSON格式输出日志,因此上面消息的结构可能看起来像这样:
{ timestamp: "20130130T12:32", message: "some message", user: "steve", request-id: "245692"... }
我可以创建一个log4j布局,可以很好地为我编写所有这些格式,但问题是我是如何将数据放在那里的。
所以我的第一个问题是:Grails里面有什么东西我可以用作“请求ID”吗?其背后的想法是为用户启动的任何“事务”提供单个请求ID。因此,控制器中的日志消息将具有与作为结果调用的域或服务类内的日志消息相同的请求ID。
第二个问题:在用户发起的交易中,是否有一种“透明地”在层(控制器/服务/域)之间“移动”移动信息的方法?如果需要,我可以在控制器中生成我自己的request-id,然后我可以获取用户名并将这两个放在地图中。但是,我如何将该映射传输到任何服务/域类和它们的记录器,而不是将其作为参数传递(我不想这样做,因为这会丢弃代码)?
任何想法都会非常感激,我应该注意到我对Grails很新,所以请保持温和; - )
答案 0 :(得分:0)
我在#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()
}
}
}
在Config中,在模式中添加%X{requestId}
log4j = {
appenders {
console name:'stdout', layout:pattern(conversionPattern: '%d{DATE} %X{requestId} %5p %c{1}:%L - %m%n')