log4j не печатает трассировку стека для исключений - PullRequest
66 голосов
/ 19 февраля 2010

Я использую log4j с Tomcat.Когда я регистрирую исключения в моих JSP, сервлеты:

private Logger _log = Logger.getLogger(this.getClass());
...
try{...} catch (Exception e) {
    _log.error("Error refreshing all prices", e);
}

Я получаю только первую строку исключения, без трассировки стека.

17-фев. 17:37:45 ОШИБКА AutoContrib: 175 - Исключение при публикации файла CSV: java.lang.ArrayIndexOutOfBoundsException

Совсем не очень полезно!

Мой файл log4j.properties (/tomcat/common/classes/log4j.properties) выглядит следующим образом:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.stdout.threshold=info

log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.maxFileSize=5000KB
log4j.appender.file.maxBackupIndex=10
log4j.appender.file.File=${catalina.home}/logs/web.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n
log4j.appender.file.threshold=info

log4j.rootLogger=debug, stdout, file

Ответы [ 8 ]

75 голосов
/ 22 февраля 2012

На самом деле, это, вероятно, связано с оптимизацией горячей точки: после выдачи определенного числа того же самого исключения оно прекращает выводить след. Это можно отключить с помощью аргумента VM, см .:

С http://www.oracle.com/technetwork/java/javase/relnotes-139183.html:

Компилятор в виртуальной машине сервера теперь обеспечивает правильные трассировки стека для всех «холодных» встроенных исключений. Для повышения производительности, когда такое исключение выдается несколько раз, метод может быть перекомпилирован. После перекомпиляции компилятор может выбрать более быструю тактику, используя предварительно выделенные исключения, которые не обеспечивают трассировку стека. Отключить полностью использовать предварительно выделенные исключения, используйте этот новый флаг: -XX: -OmitStackTraceInFastThrow

.

Подробнее здесь:

http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-to-lose-their-stack-traces-in-production-and-the-fix/

21 голосов
/ 22 февраля 2010

То, что вы опубликовали, должно отображать трассировку стека, как указано в javadoc .

Обратите внимание, что если вы не включите сообщение (и просто вызовете logger.error(ex)), тотрассировка стека не регистрируется.

15 голосов
/ 23 августа 2016

Есть два перегруженных метода для метода ошибки.

  1. logger.error(ex);
  2. logger.error("some oops string ", ex);

если вы используете 1-й метод, который будет печатать только имя исключения. если вы используете 2-й метод, какое-то сообщение вместе с исключением будет выводить полную трассировку стека, аналогично e.printStackTrace() методу.

6 голосов
/ 05 июня 2014

Как ответил @Luhar выше, я боролся с тем же, и в конце концов это сработало для меня; Хорошая вещь в этом подходе состоит в том, что нам не нужно возиться с настройками системного уровня, такими как JVM, Log4J, поскольку мы никогда не знаем, что это может привести к новому неожиданному сюрпризу!

try {

...
..

} catch (Exception er) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        er.printStackTrace(new PrintStream(os));
        LOGGER.error(new String(os.toByteArray()));
        //LOGGER.error(er);
}
1 голос
/ 19 февраля 2010

Я не использовал вызов fillStackTrace, поэтому я не могу комментировать, будет ли это работать. Другой подход заключается в использовании небольшого метода, который возвращает форматированный текст из исключения.

public static String getStackTrace(Exception e)
{
    StringWriter sWriter = new StringWriter();
    PrintWriter pWriter = new PrintWriter(sWriter);
    e.printStackTrace(pWriter);
    return sWriter.toString();
}

В своем коде регистрации вы можете написать:

logger.error("An exception occurred: " + Utils.getStackTrace(e));
1 голос
/ 19 февраля 2010

Я не вижу ничего плохого в вашей конфигурации, поэтому попробуйте обновить log4j до более новой (не обязательно до последней) версии.

Хотя это и не проблема в этом случае, вам лучше сделать свои регистраторы private static final

0 голосов
/ 26 ноября 2014

Вы можете добавить эти строки кода в свой блок catch.

catch (SQLException e) {
            CharArrayWriter cw = new CharArrayWriter();
            PrintWriter w = new PrintWriter(cw);
            e.printStackTrace(w);
            w.close();
            String trace = cw.toString();

    log.error("This is complete stacktrace", trace);
}
0 голосов
/ 19 февраля 2010

Используя ваш пример кода:

private static final Logger _log = Logger.getLogger(MyClass.class);
...
try{...} catch (Exception e) {
    //Change
    //_log.error("Error refreshing all prices", e);

   //To
    _log.error("Error refreshing all prices", e.fillInStackTrace());
}

Вы увидите всю отображаемую трассировку стека.

PS. Сделайте Logger одиночным ... (проверьте мое объявление) сразу после объявления public class MyClass {

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...