この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:T
更新日時:2026-06-11 07:10:02

タイトル: org.apache.log4j.Logger のログ出力で printStackTrace() のエラー内容を出力する方法
SEOタイトル: log4j で printStackTrace の内容をログ出力する方法(スタックトレース完全保存)

この記事の要点
  • logger.error("メッセージ", e)第 2 引数に例外オブジェクトを渡すと、Log4j が自動でスタックトレース全体をログ出力する
  • e.printStackTrace()標準エラー (System.err) に出力されるだけで、Log4j の Appender には流れない
  • 文字列として取得したい場合は ExceptionUtils.getStackTrace(e) (commons-lang3) または StringWriter + PrintWriter
  • Log4j 2 では JsonLayout / PatternLayout の %ex でスタックトレースを構造化出力できる
  • Spring Boot (logback) でも logger.error(msg, e)API は同一。引数の渡し方を統一しておくと移行が楽

結論: 例外は logger の第 2 引数で渡す

結論から書くと、例外オブジェクトを Logger の第 2 引数に渡すだけで、Log4j が自動的に printStackTrace() 相当のスタックトレースをログに書き出します。

import org.apache.log4j.Logger;

public class UserService {
    private static final Logger logger = Logger.getLogger(UserService.class);

    public void register(User u) {
        try {
            repository.save(u);
        } catch (Exception e) {
            // ★ これだけで OK。第 2 引数に例外を渡す
            logger.error("ユーザー登録に失敗しました userId=" + u.getId(), e);
            throw e;
        }
    }
}

出力例:

2026-05-17 10:23:45 ERROR UserService - ユーザー登録に失敗しました userId=123
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '123' for key 'PRIMARY'
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:109)
    at com.example.UserRepository.save(UserRepository.java:42)
    at com.example.UserService.register(UserService.java:18)
    ... 35 more

なぜ printStackTrace() ではダメなのか

e.printStackTrace() はデバッグ用の便利メソッドですが、本番運用では致命的な欠陥があります:

項目e.printStackTrace()logger.error(msg, e)
出力先標準エラー (System.err) 固定log4j.properties で定義した Appender
ログレベル制御不能ERROR / WARN / INFO を選択可
タイムスタンプなし自動付与
クラス名・スレッド名なし%c / %t で出力可
ファイル分割・ローテート不可RollingFileAppender 等で可
本番サーバーでの追跡catalina.out に埋もれる専用ログファイルに集約

とくに Tomcat や WebLogic などのアプリサーバでは、System.err は catalina.outstderr.log に流れますが、業務ログと分離されておらず原因追跡が困難になります。

NG パターン: 例外を toString() してしまう

よくある間違いが次のコードです:

// ❌ ダメな書き方
logger.error("エラー: " + e);              // toString() しか出ない
logger.error("エラー: " + e.getMessage()); // メッセージだけ、スタックトレースなし
logger.error(e.toString());                // 同上

// ❌ さらにダメ
try {
    ...
} catch (Exception e) {
    e.printStackTrace();   // 標準エラーに出るだけで Log4j に流れない
}

上記のコードは例外発生箇所が特定できず、運用フェーズで詰む典型例です。必ず第 2 引数で例外を渡してください。

スタックトレースを文字列で取得したい場合

「DB のエラー履歴テーブルに保存したい」「メール本文に含めたい」など、文字列としてスタックトレースを取り出したい場合は次の方法を使います。

方法 1: Apache Commons Lang3

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

try {
    ...
} catch (Exception e) {
    String trace = ExceptionUtils.getStackTrace(e);
    logger.error("エラー詳細:\n" + trace);

    // DB に保存
    errorLogRepository.save(new ErrorLog(e.getMessage(), trace));
}

Maven 依存:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

方法 2: 標準ライブラリの StringWriter

commons-lang3 を入れたくない場合は標準 API でも可能:

import java.io.PrintWriter;
import java.io.StringWriter;

public static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    t.printStackTrace(pw);   // ★ PrintWriter を渡せば文字列化される
    return sw.toString();
}

// 使い方
catch (Exception e) {
    String trace = getStackTrace(e);
    logger.error("エラー:\n" + trace);
}

Log4j の設定例 (log4j.properties)

スタックトレースを綺麗に出すための定番設定:

# ルートロガー: INFO 以上をファイルとコンソールへ
log4j.rootLogger=INFO, FILE, CONSOLE

# コンソール
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1} - %m%n

# ファイル (日次ローテート)
log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.FILE.File=/var/log/app/application.log
log4j.appender.FILE.DatePattern='.'yyyy-MM-dd
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c - %m%n

%m%n%m がメッセージで、第 2 引数で渡した例外のスタックトレースも自動的に %m の後ろに付加されます。

Log4j 1.x はサポート終了。Log4j 2 / SLF4J への移行

Log4j 1.x は 2015 年 8 月にサポート終了しています。新規開発では Log4j 2 または SLF4J + Logback を推奨。

// Log4j 2 (パッケージは org.apache.logging.log4j)
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

private static final Logger logger = LogManager.getLogger(UserService.class);
logger.error("失敗 userId={}", userId, e);  // ★ プレースホルダ + 末尾に例外

// SLF4J + Logback (Spring Boot 標準)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private static final Logger logger = LoggerFactory.getLogger(UserService.class);
logger.error("失敗 userId={}", userId, e);  // ★ 末尾の Throwable は自動でスタックトレース化

SLF4J / Log4j 2 では {} プレースホルダの最後の引数が Throwable なら自動的にスタックトレース出力される仕組みになっています。文字列連結 + より高速かつ安全です。

Log4j 2 で JSON 構造化ログ

ELK / Datadog / CloudWatch Logs で扱いやすい JSON 出力:

<!-- log4j2.xml -->
<Configuration>
    <Appenders>
        <Console name="JsonConsole" target="SYSTEM_OUT">
            <JsonLayout compact="true" eventEol="true" stacktraceAsString="true"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="JsonConsole"/>
        </Root>
    </Loggers>
</Configuration>

出力例 (1 行 = 1 JSON):

{"timestamp":"2026-05-17T10:23:45.123Z","level":"ERROR","logger":"UserService","message":"失敗 userId=123","thrown":{"name":"SQLIntegrityConstraintViolationException","message":"Duplicate entry","extendedStackTrace":"..."}}

FAQ

Q: catch せず throws する場合は?
A: 上位の Filter / ControllerAdvice / try-catch 側で logger.error(msg, e) すれば OK。低レベルで catch して再 throw する場合、catch のたびにログを出すと重複するので注意。

Q: スタックトレースが「... 35 more」で省略される
A: Java の仕様で、同じフレームは省略表示されます。%ex{full} や Throwable#getStackTrace() で完全取得可能。実運用ではデフォルトの省略で問題ないことが多い。

Q: 個人情報が含まれる例外メッセージをマスクしたい
A: Log4j 2 の RegexFilter や独自 Layout で正規表現マスクを実装。パスワードを例外メッセージに入れないのが原則。

Q: log4j-over-slf4j を使っているプロジェクトは?
A: コード上は org.apache.log4j.Logger のまま動きますが、実体は SLF4J 経由で Logback に流れます。API は同じなので同じ書き方で OK

関連項目

  • Log4Shell (CVE-2021-44228) — Log4j 2.0〜2.14.1 の RCE 脆弱性。Log4j 2.17.1+ への更新必須
  • SLF4J — Java ロギングのファサード。実装を切り替え可能
  • Logback — SLF4J 純正実装。Spring Boot 標準
  • Sentry / Rollbar — 例外を外部サービスに自動収集する選択肢