【问题标题】:How to log formatted message, object array, exception?slf4j:如何记录格式化消息、对象数组、异常
【发布时间】:2011-09-16 07:56:02
【问题描述】:

记录填充消息和异常堆栈跟踪的正确方法是什么?

logger.error(
    "\ncontext info one two three: {} {} {}\n",
    new Object[] {"1", "2", "3"},
    new Exception("something went wrong"));

我想产生类似这样的输出:

context info one two three: 1 2 3
java.lang.Exception: something went wrong
stacktrace 0
stacktrace 1
stacktrace ...

slf4j 版本 1.6.1

【问题讨论】:

  • 我不明白为什么 slf4j 使用自己的格式字符串语法而不是标准的 %s 样式。烦人。
  • @KeithTyler 我更喜欢{},品味问题...
  • @KeithTyler 参数的toString() 方法可能很昂贵。使用此语法,仅传递对每个对象的引用,并且仅在实际记录特定消息时才调用 toString() 方法。如果日志级别为WARN 或更高,则info() 日志调用中引用的对象将不会调用其toString() 方法。 {} 语法提醒用户这不是 String.format() 式的操作,即他们应该传递对象而不是字符串表示形式。

标签: java exception logging slf4j


【解决方案1】:

从 SLF4J 1.6.0 开始,如果存在多个参数并且日志语句中的最后一个参数是异常,那么 SL​​F4J 将假定用户希望将最后一个参数视为异常而不是简单的范围。另请参阅relevant FAQ entry

所以,写作(在 SLF4J 版本 1.7.x 及更高版本中)

 logger.error("one two three: {} {} {}", "a", "b", 
              "c", new Exception("something went wrong"));

或写作(在 SLF4J 版本 1.6.x 中)

 logger.error("one two three: {} {} {}", new Object[] {"a", "b", 
              "c", new Exception("something went wrong")});

将产生

one two three: a b c
java.lang.Exception: something went wrong
    at Example.main(Example.java:13)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at ...

确切的输出将取决于底层框架(例如 logback、log4j 等)以及底层框架的配置方式。但是,如果最后一个参数是异常,则无论底层框架如何,它都会被解释为异常。

【讨论】:

  • 您使用的是哪个底层日志框架?正如我在上面的回答中提到的,如果最后一个参数是异常,则无论底层框架如何,它都会被解释为异常。 (用 logback、slf4j-log4j12、slf4j-jdk14 和 slf4j-simple 测试。)
  • 抱歉,我不知道在您的示例中,您在格式字符串中使用了 n=3 个占位符,在对象数组中使用了 n+1=4 个元素。我在格式字符串中有 n 个占位符,在对象数组中有 n 个元素,还有一个异常作为第三个参数。我的期望是异常会用堆栈跟踪打印,但这从未发生过。这是否按设计工作?此外,如果我在对象数组中有 n 个占位符和 n 个元素,但最后一个元素是例外,我看不到任何堆栈跟踪。也许应该更加强调数组中具有 n+1 个对象的 n 个占位符。
  • 我要让 @Ceki 很难过,因为它不在 Javadocs 中,而是在 Logger javadoc 类的顶部:slf4j.org/apidocs/org/slf4j/Logger.html
  • 我创建了improvement request,喜欢的可以投一票。
  • 你知道如何让 Intellij IDEA 2020.2.3 不抱怨这个吗?它给了我一个警告The formatted log message expects N arguments, passed N-1 所以我不得不使用String.format()
【解决方案2】:

除了@Ceki 的回答,如果您正在使用 logback 并在项目中设置一个配置文件(通常是 logback.xml),您也可以使用

定义日志以绘制堆栈跟踪
<encoder>
    <pattern>%date |%-5level| [%thread] [%file:%line] - %msg%n%ex{full}</pattern> 
</encoder>

模式中的 %ex 是造成差异的原因

【讨论】:

    【解决方案3】:

    接受的答案很棒。我只是在这里添加我现在正在工作的案例,感谢您的回答。这可能对其他人有所帮助。

    我正在使用带有 JSON 编码器的 SLF4Jlogback。此外,我使用markerarguments 来丰富我的输出。

        logger.error(getMarker("errorEvent"),
                     "An error occurred",
                     entries(mapOf("someKey" to "someValue")),
                     new Exception())
    

    输出:

    { “级别”:“错误”, “事件”:“错误事件”, “事件数据”:{ “someKey”:“someValue” }, "stacktrace": "...省略...", "message": "发生错误" }

    当然logstash在幕后有很多配置,但我只是想表明,作为entries传递的arguments显示在配置的eventData标签中。

    【讨论】:

      猜你喜欢
      • 2012-09-10
      • 2011-08-22
      • 2020-11-09
      • 2012-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多