log4j:一次记录多个异常?

log4j: log multiple exceptions at once?

我有一些代码如下:

List<Exception> exceptions = new ArrayList<Exception>();
for (Foo foo : foos) {
     try {
        doStuff(foo);
     } catch (FooException ex) {
        exceptions.add(ex);
     }
}
if (!exceptions.isEmpty())
   logger.error("Exceptions occurred processing foos", exceptions);

并且在我的日志中,我会看到每个异常的完整详细信息,包括堆栈跟踪、原因链等。当然,这段代码实际上不起作用。有没有办法让一个日志条目包含所有这些?

至于为什么不在每个异常被捕获时记录下来,原因是我正在使用 SMTPAppender 并且宁愿只收到一封关于此的电子邮件。

我一直在弄乱它,我能够将列表中每个异常的堆栈跟踪组合起来传递到一个新的自定义异常中:

public class MyException extends Exception {

    public static void main(String[] args) throws MyException {

        StringWriter errors = new StringWriter();

        List<Exception> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            try {
                divideByZero(i);
            } catch (Exception e) {
                e.printStackTrace(new PrintWriter(errors));
            }
        }

        if (!errors.toString().isEmpty()) {
            throw new MyException(errors.toString());
        }
    }

    public MyException(String message) {
        super (message);
    }

    public static int divideByZero(int i) {
       return i/0;
    }
}

这是一个非常人为的例子,但我只是想传达我的想法......如果你愿意,你可以 tweak/improve 它包含更多信息。

这打印了以下内容:

Exception in thread "main" MyException: java.lang.ArithmeticException: / by zero
    at MyException.divideByZero(MyException.java:34)
    at MyException.main(MyException.java:24)
java.lang.ArithmeticException: / by zero
    at MyException.divideByZero(MyException.java:34)
    at MyException.main(MyException.java:24)
java.lang.ArithmeticException: / by zero
    at MyException.divideByZero(MyException.java:34)
    at MyException.main(MyException.java:24)

    at MyException.main(MyException.java:30)

如果您不想要异常的堆栈跟踪,您可以遍历列表并在每个异常的日志语句中调用 getMessage(或 getLocalisedMessage)方法。那应该打印出异常的类型和原因。

这是简单干净的方法:

1。创建您自己的异常,例如:

class CompositeException extends Exception {
    private final List<Exception> es;

    public CompositeException(Exception[] es) {
        this.es = Arrays.asList(es);
    }

    public CompositeException(List<Exception> es) {
        this.es = new ArrayList<Exception>(es);
    }

    @Override
    public void printStackTrace(PrintStream s) {
        for (Throwable e : this.es) {
            e.printStackTrace(s);
        }
    }
}

2。然后使用 CompositeException class:

List<Exception> exceptions = new ArrayList<Exception>();
for (Foo foo : foos) {
    try {
        doStuff(foo);
    } catch (FooException ex) {
        exceptions.add(ex);
    }
}