Как зарегистрировать трассировку стека с помощью класса java Logger

Я использую класс Java Logger. Я хочу передать ex.printStackTrace() в Logger.log(loglevel, String), но printStackTrace() возвращает void. Поэтому я не могу передать и распечатать трассировку стека исключения.

Есть ли способ преобразовать void в String или есть какие-либо другие методы для печати всей трассировки стека исключений?


person Surya Joseph    schedule 14.07.2015    source источник
comment
короче: НЕТ, ты не можешь.   -  person Bacteria    schedule 14.07.2015
comment
Конечно, используйте это: commons.apache.org/proper/commons-lang/javadocs/api-3.4/org/ из commons-lang3 3.4   -  person EpicPandaForce    schedule 14.07.2015
comment
В какое строковое значение ничего бы не превратилось?   -  person user2864740    schedule 14.07.2015


Ответы (13)


Вы должны понимать, что void на самом деле nothingness. Вы не можете преобразовать то, что ничто. Вы можете в конечном итоге напечатать void в виде строки, но (поверьте мне), вы этого не хотите.

Я думаю, что вы ищете

// assuming ex is your Exception object
logger.error(ex.getMessage(), ex);
// OR
Logger.log(errorLogLevel, ex.getMessage(), ex)

Это напечатает сообщение об ошибке, используя настроенный вами регистратор. Дополнительные сведения см. в документации по java для Исключение#getMessage()

person Saif Asif    schedule 14.07.2015
comment
Спасибо, Саиф Асиф. Теперь я могу регистрировать всю трассировку стека. - person Surya Joseph; 14.07.2015
comment
logger.error() не java.util.logging, но я не буду минусовать вас, потому что я рад открыть для себя logger.log(Level, Exception, Supplier). Похоже, Oracle сделала java.util.logging.Logger серьезно уродливым! Так как они это делали, странно, что они не пошли дальше и не создали logger.severe(String, Exception) и т.д. - person Adam; 11.10.2017
comment
Вопрос требует решения с использованием класса Logger Java. java.util.logging.Logger не имеет метода с именем error. Я понизил этот ответ только из-за этого. - person DAB; 28.08.2018
comment
@Adam Адам, я согласен с тем, что logger.error() выглядит уродливо, но он легко читается, и именно так это делается в других простых языках, таких как python, так что это не так уж и плохо. - person DGoiko; 14.03.2019
comment
Это вообще не отвечает первоначальному намерению распечатать трассировку стека в регистраторе. getMessage() не предназначен для этого. - person A. Gille; 22.05.2020
comment
Итак, ответ: logger.log(Level.SEVERE, ex.getMessage(), ex); - person Kenny; 14.10.2020

Используйте java.util.logging.Logger#log(Level, String, Throwable) и передайте ex в качестве третьего аргумента следующим образом:

LOGGER.log(Level.INFO, ex.getMessage(), ex);
person hzpz    schedule 14.07.2015
comment
Я не получаю трассировку стека для регистрации с этим, только второй аргумент. - person Panu Haaramo; 13.01.2018
comment
Можно подавить трассировку стека, изменив формат журнала. Какой форматировщик вы используете и как выглядит ваш формат журнала? - person hzpz; 19.01.2018
comment
Это реальный ответ на вопрос. - person steinybot; 04.04.2019
comment
@PanuHaaramo Это зависит от того, какой форматировщик вы используете. Средство форматирования должно вызвать record.getThrown() в format. Взгляните на SimpleFormatter. - person steinybot; 04.04.2019

Также другой альтернативой может быть:

import org.apache.commons.lang3.exception.ExceptionUtils;

log.error("Exception : " + ExceptionUtils.getStackTrace(exception));
person Rutuja    schedule 19.04.2018
comment
Если вы имеете в виду org.apache.commons.lang3.exception.ExceptionUtils, это ExceptionUtils.getStackTrace(e) - person JoschJava; 04.09.2018

В приведенном ниже формате вы можете получить трассировку стека:

java.util.logging.SimpleFormatter.format=%1$tF %1$tT [%4$-7s][%2$s] %5$s %6$s%n

Точка в этом шаблоне — %6$s. Он напечатает трассировку стека.

person iman    schedule 08.08.2018

Вы не можете преобразовать void в String; такого преобразования не существует. void не возвращает ничего обратно, поэтому у вас нет значения для извлечения.

Вместо этого вы, вероятно, захотите получить сообщение об исключении через ex.getMessage().

person Makoto    schedule 14.07.2015

Существует перегруженный метод printStackTrace, который принимает объект PrintWriter.

Вы можете сделать что-то вроде этого

Writer buffer = new StringWriter();
PrintWriter pw = new PrintWriter(buffer);
ex.printStackTrace(pw);
Logger.log(loglevel, buffer.toString());
person sleeloy    schedule 14.07.2015
comment
Это самый простой метод IMHO, и он действительно печатает трассировку стека, а не только сообщение. - person Marco Sulla; 21.05.2021

Вы можете использовать getStackTrace(), чтобы получить массив StackTraceElements и сгенерировать оттуда строку. В противном случае, если достаточно последнего сообщения об ошибке, используйте метод getMessage(), предложенный Макото.

Чтобы получить трассировку стека в виде String из массива объектов StackTraceElement, вам нужно выполнить итерацию по массиву (взятому из исходного кода JDK7):

StringBuilder builder = new StringBuilder();
StackTraceElement[] trace = getOurStackTrace();
    for (StackTraceElement traceElement : trace)
        builder.append("\tat " + traceElement + "\n");

Другой вариант — использовать printStackTrace(PrintStream s), где вы можете указать, где вы хотите распечатать трассировку стека:

ByteArrayOutputStream out1 = new ByteArrayOutputStream();
PrintStream out2 = new PrintStream(out1);
ex.printStackTrace(out2);
String message = out1.toString("UTF8");
person Chthonic Project    schedule 14.07.2015
comment
Просто используйте библиотеку Apache Commons ExceptionUtils; не нужно изобретать велосипед - person beresfordt; 14.07.2015
comment
1. String message = out1.toString("UTF8"); - ошибка компиляции, ожидал 0 параметреров, а получил 1 2. Работает корректно out2.out.toString. В случае out2.toString -> 'PrintStream@hash' - person Nikita; 20.11.2019

Вы можете использовать ExceptionUtils, если вам нужно увидеть трассировку стека без создания исключения.

String stackTrace = ExceptionUtils.getStackTrace(new Exception("YourMessage"));
log.error(stackTrace);
person Anton Tevs    schedule 23.10.2020

Как говорит Макото, вы, вероятно, захотите сделать ex.getMessage().

Чтобы уточнить, void означает, что ничего не возвращается. Вы ничего не можете бросить во что-то :)

person kotakotakota    schedule 14.07.2015
comment
Ему нужна трассировка стека, а не только сообщение. - person Oliv; 17.05.2019

вы МОЖЕТЕ преобразовать stacktrace в String, используя ниже. Если e является объектом исключения

StringWriter stringWriter= new StringWriter();
PrintWriter printWriter= new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
String stackTraceAsString= stringWriter.toString(); 
person Amit.rk3    schedule 14.07.2015

Спасибо вам всем. Я могу регистрировать детали трассировки стека, используя

LOGGER.log(Level.INFO, ex.getMessage(),ex);
//ex is my exception object
person Surya Joseph    schedule 14.07.2015

Вы также можете использовать ExceptionUtils из библиотеки apache или ниже оператора журнала

    try{
      doSomething();
    }
    catch(Exception e){
    log.error("Exception in method doSomething ",e);
    }
person Saurabh    schedule 28.10.2019

Все предыдущие предложения, похоже, просто помещают трассировку стека в журнал без префикса каждой строки с данными регистратора. Мое предложение ниже обрабатывает элементы трассировки стека и форматирует каждую строку как строку регистратора:

log.error("{}", e.toString());
StackTraceElement[] stElements = e.getStackTrace();

log.error("(stacktrace) {}", e.toString());

for (StackTraceElement ste: stElements) {
    log.error("(stacktrace)     at {}.{}({}.java:{})", 
        new Object[] {ste.getClassName(), ste.getMethodName(), 
                      ste.getClassName(), ste.getLineNumber()});
}

Throwable thisThrowable = e;
boolean causedBy = true;
while (causedBy) {
    Throwable throwable = thisThrowable.getCause();
    if (throwable != null) {
        log.error("(stacktrace) Caused by: {}", throwable.toString());
        stElements = throwable.getStackTrace();
        for (StackTraceElement ste: stElements) {
            log.error("(stacktrace)     at {}.{}({}.java:{})", 
                 new Object[] {ste.getClassName(), ste.getMethodName(),                    
                               ste.getClassName(), ste.getLineNumber()});
        }
        thisThrowable = throwable;  // For the next caused-by check
    } else {
        log.error("(stacktrace) No Caused-by Exception");
        causedBy = false;  // No more caused-by Throwables, so end the loop
    }
}

Каждая строка трассировки стека имеет префикс (stacktrace). Это имеет то преимущество, что позволяет отфильтровывать их при создании дампа файлов журнала или легко их находить.

person hairysocks    schedule 18.06.2021