Как отправить stacktrace в 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 );
}

Ответ 1

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

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

Это до log4j для отображения трассировки стека.

Ответ 2

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

Смотрите: ExceptionUtils.java

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

Ответ 3

Если вы хотите зарегистрировать stacktrace без привлечения исключения, просто выполните это:

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

Ответ 4

Этот ответ может быть не связан с вопросом, но связан с заголовком вопроса.

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

ИЛИ

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

ИЛИ

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

Ответ 5

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

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

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

Ответ 6

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

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

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

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

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

Я на самом деле написал библиотеку с открытым исходным кодом, которая имеет Утилиту для извлечения stacktrace как String с возможностью изящно отфильтровать некоторый шум из stacktrace. То есть если вы укажете префикс пакета, который вам интересен в вашем извлеченном стеке, будет отфильтрован из некоторых нерелевантных частей и оставит вас с очень интересной информацией. Вот ссылка на статью, в которой объясняются, какие утилиты есть в библиотеке и где ее получить (как артефакты maven, так и источники git), и как их использовать. Библиотека Java с открытым исходным кодом с фильтрацией трассировки стека, синтаксический анализ строк Unicode-конвертер и сравнение версий См. параграф " Фильтр шума Stacktrace"

Ответ 7

это было бы хорошо log4j error/exception logging - читается с помощью splunk/other logging/monitoring s/w. все это форма пары ключ-значение. 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});
    }

Ответ 8

Try this:

catch (Throwable t) {
    logger.error("any message" + t);
    StackTraceElement[] s = t.getStackTrace();
    for(StackTraceElement e : s){
        logger.error("\tat " + e);
    }   
}

Ответ 9

Вы можете использовать приведенный ниже код:

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 в ваш журнал.

Ответ 10

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

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

Ответ 11

Создайте этот 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();