Как отправить трассировку стека в log4j?

Предположим, вы перехватили исключение и получили на стандартный вывод (например, консоль) следующее, если вы выполнили e.printStackTrace ():

java.io.FileNotFoundException: so.txt
        at java.io.FileInputStream.<init>(FileInputStream.java)
        at ExTest.readMyFile(ExTest.java:19)
        at ExTest.main(ExTest.java:7)

Теперь я хочу отправить это вместо регистратора, например, log4j, чтобы получить следующее:

31947 [AWT-EventQueue-0] ERROR Java.io.FileNotFoundException: so.txt
32204 [AWT-EventQueue-0] ERROR    at java.io.FileInputStream.<init>(FileInputStream.java)
32235 [AWT-EventQueue-0] ERROR    at ExTest.readMyFile(ExTest.java:19)
32370 [AWT-EventQueue-0] ERROR    at ExTest.main(ExTest.java:7)

Как я могу это сделать?

try {
   ...
} catch (Exception e) {
    final String s;
    ...  // <-- What goes here?
    log.error( s );
}

person SyntaxT3rr0r    schedule 03.12.2010    source источник


Ответы (10)


Вы передаете исключение непосредственно регистратору, например

try {
   ...
} catch (Exception e) {
    log.error( "failed!", e );
}

Отрисовку трассировки стека выполняет log4j.

person skaffman    schedule 03.12.2010
comment
Регистратор принимает объект в качестве первого аргумента и выполняет его toString (). Однако второй аргумент должен быть Throwable и отображать трассировку стека. - person Peter Lawrey; 03.12.2010
comment
Я никогда не знаю, что вставить в первую строку, обычно я просто делаю log.error(e.getLocalizedMessage(), e), что полностью избыточно. Обрабатывает ли он нулевое значение для первого аргумента? - person Mark Peters; 03.12.2010
comment
@Mark: попробуйте дать ему сообщение, более подходящее для контекста, чем сообщение об исключении, например что он на самом деле пытался сделать в то время? - person skaffman; 03.12.2010
comment
@Mark Peters, хорошим примером может быть регистрация аргументов текущего метода в виде сообщения или - для исключения FileNotFound - полного имени пути, который пытались открыть. Все, что может помочь вам выяснить, что не так - просто подумайте, что вы не можете отладить ситуацию. - person Thorbjørn Ravn Andersen; 03.12.2010
comment
Я согласен с Торбьёрном Равном Андерсеном. Одна из самых полезных вещей, которые можно сделать при постоянно меняющихся веб-приложениях, - это распечатать SQL для всех операций с базой данных. Если вы поместите много новых строк, чтобы каждая часть была отдельной строкой, ваш клиент базы данных сообщит вам, где именно находится ошибка, если вы вставите ее и выполните ее. - person Steve; 06.08.2011
comment
@skaffman: На самом деле я использую log4j-1.2.8.jar, и я хотел напечатать все stackTrace в моем файле журнала, поэтому я пробовал, как вы упомянули выше, но в моем файле журнала печатается только nullPointerException. Я использовал свой код e.printStackTrace(), он печатает всю трассировку. Почему этот Колавер? - person Yubaraj; 10.09.2013
comment
Log4j позволяет настраивать глубину трассировки стека, добавляемую в журналы. Если вы выполните трассировку стека самостоятельно, вы обойдете это настраиваемое значение. Примечание по выбрасыванию SQL: если вы используете подготовленные операторы, у вас может не быть доступа к вставляемой завершенной команде SQL. Например, вызов toString для подготовленного оператора Oracle не возвращает SQL. - person ChrisCantrell; 20.06.2016
comment
Очевидно, вам нужно включить сообщение в свой журнал, иначе оно не сработает: stackoverflow.com/a/2307917/1545084 - person Gladclef; 24.05.2017

Если вы хотите записать трассировку стека без исключения, просто сделайте следующее:

String message = "";

for(StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {                         
    message = message + System.lineSeparator() + stackTraceElement.toString();
}   
log.warn("Something weird happened. I will print the the complete stacktrace even if we have no exception just to help you find the cause" + message);
person borjab    schedule 28.08.2014
comment
+1 для System.lineSeparator (), это помогло мне распечатать трассировку стека, которую я получил в качестве ответа от удаленной службы. - person Stephanie; 13.05.2016
comment
то, что я искал, но вы должны использовать StringBuilder здесь - person Xerus; 01.11.2017

Вы также можете получить трассировку стека в виде строки через ExceptionUtils.getStackTrace.

См .: ExceptionUtils.java

Я использую его только для log.debug, чтобы log.error было проще.

person ktsujister    schedule 23.02.2012

Ответ Скаффмана определенно правильный. Все методы регистратора, такие как error(), warn(), info(), debug(), принимают Throwable в качестве второго параметра:

try {
...
 } catch (Exception e) {
logger.error("error: ", e);
}

Однако вы также можете извлечь stacktrace как строку. Иногда это может быть полезно, если вы хотите воспользоваться функцией форматирования с использованием заполнителя "{}" - см. Метод void info(String var1, Object... var2);. В этом случае, скажем, у вас есть трассировка стека как String, тогда вы действительно можете сделать что-то вроде этого:

try {
...
 } catch (Exception e) {
String stacktrace = TextUtils.getStacktrace(e);
logger.error("error occurred for usename {} and group {}, details: {}",username, group, stacktrace);
}

Это напечатает параметризованное сообщение и трассировку стека в конце так же, как и для метода: logger.error("error: ", e);

На самом деле я написал библиотеку с открытым исходным кодом, в которой есть утилита для извлечения трассировки стека в виде строки с возможностью умной фильтрации некоторого шума из трассировки стека. Т.е. если вы укажете префикс пакета, который вас интересует, ваша извлеченная трассировка стека будет отфильтрована из некоторых нерелевантных частей и оставит вам очень сжатую информацию. Вот ссылка на статью, в которой объясняется, какие утилиты есть в библиотеке и где их взять (как артефакты maven, так и источники git), а также как их использовать. Библиотека Java с открытым исходным кодом с фильтрацией трассировки стека, Тихий анализ строки Конвертер Unicode и сравнение версий См. Параграф «Фильтр шума Stacktrace».

person Michael Gantman    schedule 04.07.2017
comment
Скрытый, но приятный ответ. - person payne; 20.11.2019
comment
Спасибо, @payne. Я ценю хороший отзыв - person Michael Gantman; 20.11.2019
comment
Спасибо. Я остановился на этом вопросе, потому что искал именно этот ответ. - person axiopisty; 28.01.2021
comment
@axiopisty - пожалуйста. Я рада, что это было полезно для тебя - person Michael Gantman; 28.01.2021

Просто потому, что это случилось со мной и может быть полезно. Если ты сделаешь это

try {
   ...
} catch (Exception e) {
    log.error( "failed! {}", e );
}

вы получите заголовок исключения, а не всю трассировку стека. Поскольку регистратор будет думать, что вы передаете String. Сделайте это без {}, как сказал скаффман

person iberbeu    schedule 30.06.2014
comment
Конечно, здесь вы получите всю трассировку стека, однако {} тоже будет напечатано дословно (без какой-либо подстановки)? - person k1eran; 25.02.2015
comment
не будь так уверен, мой друг! У меня не получилось, достал только заголовок. Это может зависеть от версии log4j, хотя - person iberbeu; 25.02.2015
comment
@iberbeu прав, потому что Throwable.toString() не возвращает трассировку стека. (Предполагая, что вы используете регистратор, который знает, что делать с '{}'.) - person ; 09.01.2019

Этот ответ может быть связан не с заданным вопросом, а с названием вопроса.

public class ThrowableTest {

    public static void main(String[] args) {

        Throwable createdBy = new Throwable("Created at main()");
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintWriter pw = new PrintWriter(os);
        createdBy.printStackTrace(pw);
        try {
            pw.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.debug(os.toString());
    }
}

OR

public static String getStackTrace (Throwable t)
{
    StringWriter stringWriter = new StringWriter();
    PrintWriter  printWriter  = new PrintWriter(stringWriter);
    t.printStackTrace(printWriter);
    printWriter.close();    //surprise no IO exception here
    try {
        stringWriter.close();
    }
    catch (IOException e) {
    }
    return stringWriter.toString();
}

OR

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
for(StackTraceElement stackTrace: stackTraceElements){
    logger.debug(stackTrace.getClassName()+ "  "+ stackTrace.getMethodName()+" "+stackTrace.getLineNumber());
}
person Kanagavelu Sugumar    schedule 28.09.2013

В Log4j 2 вы можете использовать Logger.catching () для регистрации трассировки стека из обнаруженного исключения.

    try {
        String msg = messages[messages.length];
        logger.error("An exception should have been thrown");
    } catch (Exception ex) {
        logger.catching(ex);
    }
person mbonness    schedule 14.10.2019

это было бы неплохо для журнала ошибок / исключений log4j - его может читать splunk / другое программное обеспечение для ведения журнала / мониторинга. все представляет собой пару "ключ-значение". log4j получит трассировку стека из Exception obj e

    try {
          ---
          ---
    } catch (Exception e) {
        log.error("api_name={} method={} _message=\"error description.\" msg={}", 
                  new Object[]{"api_name", "method_name", e.getMessage(), e});
    }
person src3369    schedule 10.08.2017

Вы можете использовать следующий код:

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public class LogWriterUtility {
    Logger log;

    public LogWriterUtility(Class<?> clazz) {
        log = LogManager.getLogger(clazz);
    }

public void errorWithAnalysis( Exception exception) {

        String message="No Message on error";
        StackTraceElement[] stackTrace = exception.getStackTrace();
        if(stackTrace!=null && stackTrace.length>0) {
            message="";
            for (StackTraceElement e : stackTrace) {
                message += "\n" + e.toString();
            }
        }
        log.error(message);


    }

}

Здесь вы можете просто позвонить: LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

Он напечатает stackTrace в вашем журнале.

person Md. Sajedul Karim    schedule 02.08.2018

Создайте это class:

public class StdOutErrLog {

private static final Logger logger = Logger.getLogger(StdOutErrLog.class);

public static void tieSystemOutAndErrToLog() {
    System.setOut(createLoggingProxy(System.out));
    System.setErr(createLoggingProxy(System.err));
}

public static PrintStream createLoggingProxy(final PrintStream realPrintStream) {
    return new PrintStream(realPrintStream) {
        public void print(final String string) {
            logger.info(string);
        }
        public void println(final String string) {
            logger.info(string);
        }
    };
}
}

Назовите это в своем коде

StdOutErrLog.tieSystemOutAndErrToLog();
person user2281804    schedule 15.04.2013