java - 你如何在 slf4j 中格式化异常?

标签 java logging slf4j slf4j-api

网上找的很多例子,the documentation在这里 Stack overflow , 在 slf4j 中连接字符串的正确方法是使用内置的字符串格式。

例如:

    LOGGER.error("ExceptionHandler throws {}" , appException);

我也试过没有格式化,结果是一样的:

    LOGGER.error("ExceptionHandler throws " , appException);

出于某种原因,这对我不起作用,我不知道我错过了什么。如果我们传递一个对象,我们会使用不同的格式吗?

上面的示例正在打印以下日志消息:

2018-07-18 02:38:19 ERROR c.a.c.c.p.ExceptionProcessor:67 - ExceptionHandler throws  {}

而不是我在使用常规连接时收到的预期消息:

LOGGER.error("ExceptionHandler throws " + appException);

或者当我手动调用 .toString() 时

   LOGGER.error("ExceptionHandler throws {}" , appException.toString());

根据 Sonar 的说法,最后一个选项是不正确的,因为:

Because printf-style format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that result in the wrong strings being created. This rule statically validates the correlation of printf-style format strings to their arguments when calling the format(...) methods of java.util.Formatter, java.lang.String, java.io.PrintStream, MessageFormat, and java.io.PrintWriter classes and the printf(...) methods of java.io.PrintStream or java.io.PrintWriter classes.

AppException 类如下:

import java.io.Serializable;

import javax.ws.rs.core.Response.Status;


public class AppException extends Exception implements Serializable {

    private static final long serialVersionUID = 1L;

    private Error error;
    private Status status;

    public AppException(Error error, Status status) {
        this.error = error;
        this.status = status;
    }

    public AppException() {
    }

    public Error getError() {
        return error;
    }

    public void setError(Error error) {
        this.error = error;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "AppException [error=" + error + ", status=" + status + "]";
    }

}

我正在构建我的记录器如下:

private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionProcessor.class);

我正在使用 slf4j-api 1.7.22

最佳答案

您相信 LOGGER.error("ExceptionHandler throws {}", appException); 正在调用:

error(String format, Object arg)

但它实际上是在调用:

error(String msg, Throwable t)

因为这更适合参数类型。

如果你想让它调用第一个,将参数转换为Object:

LOGGER.error("ExceptionHandler throws {}" , (Object) appException);

或者像您已经尝试过的那样调用 toString()

如果您使用一个好的 IDE 来编写代码,IDE 会帮助您解决这个问题。例如。在 Eclipse 中,如果将鼠标悬停在方法调用上,它会准确显示正在调用的方法。当存在过载时非常有用。


I just rebuilt the code , and added two log entries : one with a call to toString and another with the casting you are proposing. The one with the casting is not working as expected and is producing the result I posted initially (no message)

无法重现。这是 MCVE(使用 org.slf4j:slf4j-simple:1.7.25):

Logger logger = LoggerFactory.getLogger("Test");
Exception e = new Exception("Test");
    
logger.error("Test 1: {}", e);           // calls error(String, Throwable)
logger.error("Test 2: {}", (Object) e);  // calls error(String, Object)

输出

[main] ERROR Test - Test 1: {}
java.lang.Exception: Test
    at Test.main(Test.java:8)
[main] ERROR Test - Test 2: java.lang.Exception: Test

第一次调用按原样打印消息(使用 {})和堆栈跟踪。
第二次调用用异常文本替换了 {} 的打印消息。

关于java - 你如何在 slf4j 中格式化异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51392973/

相关文章:

java - 使用 Jsoup 从 HTML 表中提取数据

java - 消费者在我的简单 Java 生产者/消费者/队列代码中不起作用

java - 寻找与数据库设计相关的方式

java - 使用具有不兼容依赖项的 Java 库

java - 在 Oracle 中将 NUMBER 保存为 TIMESTAMP

java - 克隆 SpannableStringBuilder

java - Vigenère密码实现

MATLAB 中的记录函数参数

c# - System.IO.IOException C# 当 FileInfo 和 WriteAllLines

java - 使用 slf4j 为每个记录的消息添加静态前缀