Log4j не печатает stacktrace для исключений

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

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

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

17-Feb 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

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

Как ответил @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);
}

Ответ 5

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

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));

Ответ 6

Используя образец кода:

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 singleton... (проверьте мое объявление) сразу после объявления public class MyClass {

Ответ 7

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

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

Ответ 8

Вы можете добавить эти строки кода в свой блок 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);
}