web-dev-qa-db-ja.com

スタックトレースを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 );
}
147
SyntaxT3rr0r

例外をロガーに直接渡します。

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

スタックトレースをレンダリングするのはlog4jです。

251
skaffman

例外を伴わずにスタックトレースを記録したい場合は、次のようにします:

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

ExceptionUtils.getStackTraceを介して文字列としてスタックトレースを取得することもできます。

参照: ExceptionUtils.Java

log.debugをシンプルにするために、log.errorにのみ使用します。

8
ktsujister

この回答は、尋ねられた質問に関連するのではなく、質問のタイトルに関連する場合があります。

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

それは私に起こったし、役に立つことができるからです。これをするなら

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

スタックトレース全体ではなく、例外のヘッダーを取得します。ロガーは文字列を渡していると考えるからです。スカッフマンが言ったように{}なしでそれをしなさい

2
iberbeu

スカッフマンからの答えは間違いなく正しい答えです。 error()warn()info()debug()などのすべてのロガーメソッドは、Throwableを2番目のパラメーターとして受け取ります。

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

ただし、スタックトレースも文字列として抽出できます。 「{}」プレースホルダーを使用してフォーマット機能を利用したい場合に役立つことがあります-メソッドvoid info(String var1, Object... var2);を参照してくださいこの場合、文字列としてスタックトレースがあると言うと、実際には次のようなことができます:

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コンバーター、およびバージョン比較スタックトレースノイズフィルター

2
Michael Gantman
Try this:

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

以下のコードを使用できます。

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がログに出力されます。

0

これは、log4jエラー/例外のログを記録するのに適しています-splunk /その他のログ/監視ソフトウェアで読み取り可能です。すべてがキーと値のペアの形式です。 log4jは、例外obj eからスタックトレースを取得します

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