【问题标题】:IDs for log messages when using SLF4J使用 SLF4J 时的日志消息 ID
【发布时间】:2013-11-15 17:02:31
【问题描述】:

我想为日志语句添加一个唯一标识符,这样我就可以为每个日志语句添加文档(外部,例如 wiki),以便用户可以使用该 ID 快速访问与消息相关的文档。我想使用的日志框架是 SLF4J/logback。

除了一些关于审计框架的信息外,我找不到有关相关方法的文档。

我认为标记概念可用于 ID 注入,或者我可以将 ID 添加到消息文本本身。

如何以“正确的方式”将 ID 添加到日志记录语句中?有没有我没有想到的可能性?

编辑

unique ID 一词只是指出 应该 是每个日志语句的标识符。开发人员,例如手动将这样的 ID 添加到表/枚举/任何内容中,这可能是错误的。 这样的 ID 必须是稳定的,所以文档可以基于它。所以 ID 本身并不是我想知道的。

我的问题是:将 ID 与消息文本一起推送到记录器的正确方法是什么?标记是否适合这种要求,我应该将 ID 嵌入到消息文本中还是有其他可能性?

所以,基本上,我会使用

logger.info(IDMarkers.DB_CONNECTION_FAILED, "no connection to the database");

或者只是

logger.info("[{}] no connection to the database", LogIDs.DB_CONNECTION_FAILED);

第一种方法的优点是显示 ID 取决于日志记录系统/它的配置。

【问题讨论】:

  • 您希望 id 如何唯一?通过电话?通过线程?按代码行?
  • @zenbeni:日志语句(例如 logger.debug('some message text') )应该获取 ID。这样的声明会产生例如每次通话都有一个类似[ID1234] some message text 的日志条目。
  • 在运行时获取执行上下文很昂贵:stackoverflow.com/questions/17473148/… 所以我认为你应该在消息中静态地进行。
  • @zenbeni:我可能错了,但获取标记并不比从其他地方获取 ID 所需的字符串连接更昂贵。这不会涉及获取执行上下文。
  • 在更多谷歌搜索后发现this有关SO的相关问题,不幸的是没有太多信息。

标签: java logging slf4j


【解决方案1】:

Slf4j 有http://www.slf4j.org/apidocs/org/slf4j/Marker.html

不幸的是,Markers 被宣传用于不同的目的。您仍然可以使用它们来唯一地标记日志记录。

比较麻烦的解决方案是MDC:

MDC.put("MsgId", "EV-1234");
log.info()
MDC.remove("MsgId");

或使用结构化日志记录(需要 v2.0.0):

logger.atDebug()
    .addKeyValue("MsgId", "EV-1234")
    .log("Temperature changed.");          

【讨论】:

    【解决方案2】:

    Unique 仅在某个范围内是唯一的。最终,甚至每个 intlong 值都会被使用。

    所以想想“独特性”对你意味着什么。然后使用一个包装器来确保您的日志记录是在插入该 ID 的情况下处理的。

    请注意,使用 slf4j 您正在处理 interface,这将使许多日志记录 API一致。这意味着您可能无法选择子类甚至注入接口的实现以确保您的日志记录一致。因此,您将受限于包装日志 API 等技术(最好通过“一致”接口)。

    package mypackage.log;
    
    public class LoggerWrapper implements org.log4j.Logger {
    
       private org.log4j.Logger logger;
    
       public LoggerWrapper(org.log4j.Logger logger) {
         this.logger = logger;
       }
    
       public String getUniqueId() {
         return ...;
       }
    
       public void info(String message, Object params...) {
         logger.info(String.format("[%d] %s", getUniqueId(), message), params));
       }
    
       ... implement all the other methods ...
    }
    

    这意味着你也必须制作自己的LoggerFactory 接口

    public Logger getLogger(String name) {
      return new LoggerWrapper(org.sql4j.LoggerFactory(name));
    }
    

    虽然上面的代码有一些缺陷(实际上并未对其进行测试);希望它能给你一个想法。

    【讨论】:

    • 我更新了我的问题以指出它的方向。您提出的解决方案将为每个日志条目提供一个唯一 ID,这不支持我将文档链接到日志语句...
    • 我的解决方案会给你一个你想要的任何东西的唯一 ID。例如,您可以使用常量字符串构造包装器,然后它将是每个记录器的唯一日志 ID。或者您可以使用getUniqueId() 中的线程检测代码为每个线程设置一个唯一的 ID。由您决定唯一性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多