Java開発におけるログ出力は、障害解析・性能改善・監査の三種の神器。長年使われてきた log4j 1.x に対し、後継の log4j2 は「高速・柔軟・安全」に大幅進化しています。本稿では、違いが直感的に分かる比較と、**失敗しない導入手順(Maven/Gradle、設定、非同期化、移行の落とし穴まで)**をまとめます。
1. log4j 1.x と log4j2 の要点比較
観点 | log4j 1.x | log4j2 |
---|---|---|
パフォーマンス | 同期中心。大量ログでアプリに負荷 | LMAX Disruptorによる非同期ロガーで高速・低レイテンシ |
設定形式 | properties / XML のみ | XML / JSON / YAML / properties、ホットリロード対応 |
非同期化 | AsyncAppenderのみ | AsyncAppender+Async Logger(全ロガー非同期も可) |
GC負荷 | 文字列連結が発生しやすくGC負担増 | 遅延評価(ラムダ/プレースホルダ)で不要時は連結処理なし |
拡張性 | 限定的 | フィルタ / レイアウト / Appender が豊富(JSON出力、Failover等) |
メンテナンス | EoL(保守終了) | 現行バージョン維持(常に最新2.xを推奨) |
結論:高負荷・可観測性重視の現場ほど log4j2 一択。
2. こんな場面で「log4j2」を選ぶ
-
大量ログ(秒間1000件~万件)を裁くWeb/バッチ、IoT、決済、EC
-
本番でログレベルを動的変更したい(再起動なしで即調査)
-
JSON出力で Elasticsearch / OpenSearch / Splunk / Datadog に流す
-
遅延評価や MDC(相関ID) で可観測性とパフォーマンスを両立したい
3. 導入手順(Maven/Gradle)――最短で“動く”まで
ここでは log4j2 を実装(Core)として使い、APIは SLF4J で書く構成を推奨します。
理由:ライブラリ間の共通言語として SLF4J がデファクト、実装差し替えも容易。
3.1 依存関係を追加
Maven(pom.xml)
Gradle(Kotlin DSL)
重要:既存で引き込まれる logback-classic や slf4j-log4j12 は除外してください(重複実装エラー&二重出力の原因)。
3.2 旧実装の衝突を避ける(例:Maven の除外)
3.3 最小構成の設定ファイル(src/main/resources/log4j2.xml
)
-
monitorInterval="30"
:30秒ごとに設定ファイルの変更を検知し、再起動なしで反映。
3.4 SLF4J での利用コード
3.5 ローリングファイル+JSON(実戦向け)
-
JSON出力で可観測性基盤にそのまま投入可能。
-
max="30"
:古いファイルを30世代で自動削除。
3.6 非同期化の推奨設定(高スループット向け)
方法A:Async Appender(部分的に非同期)
方法B:Async Logger(全ロガーを非同期化)
-
依存に
disruptor
を追加(前述) -
JVM 起動オプションに以下を付与
1-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
目安:秒間数千件以上のログ、遅延許容な処理では Async Logger が強力。
低遅延の必要なクリティカル処理(トランザクション境界直前など)は同期Appenderで分離も可。
3.7 現場で必須の“相関ID”(MDC/ThreadContext)
-
分散トレーシングやバッチ内のジョブ相関に必須。
3.8 動的なログレベル変更(コード&設定)
-
コードで変更
-
設定のホットリロード:
monitorInterval
でファイルを書き換えるだけ
3.9 他フレームワークのログを一本化(任意)
-
JUL(java.util.logging)→ Log4j2:
log4j-jul
を追加し、1-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -
Commons Logging(JCL)→ Log4j2:
log4j-jcl
を追加
4. 旧 log4j 1.x からの移行チェックリスト
-
jar の置換と衝突解消
-
1.x の
log4j-1.2.x.jar
を除去 -
log4j-api
,log4j-core
,log4j-slf4j2-impl
を追加 -
他実装(logback 等)を除外
-
-
設定ファイルを置き換え
-
log4j.properties
→log4j2.xml(or .json/.yaml)
に構造変換
-
-
コードの修正方針(推奨順)
-
SLF4J API へ書き換え(
LoggerFactory.getLogger
等) -
もしくは log4j2 API へ(
org.apache.logging.log4j.LogManager.getLogger
) -
当面の暫定策として
log4j-1.2-api
(互換レイヤ)もあるが恒久利用は非推奨
-
-
性能と出力の検証
-
期待QPSでのバックプレッシャやディスク枯渇を確認
-
非同期化の有無でレイテンシ差を測定
-
-
運用監視
-
-Dlog4j2.debug=true
で起動し、設定解決やエラーを起動時に確認 -
ログローテーションと世代数の上限を監視に組み込み
-
5. 開発・運用の実用Tips
-
重い
toString()
を直接連結しない:log.debug("x={}", () -> obj.heavyToString())
-
Failover Appender で出力先障害に備える(ネットワークストレージ等)
-
パターン設計:時刻、レベル、ロガー、メッセージ、
%throwable
、MDC を最低限 -
本番では INFO 以上、詳細調査時のみ一時的に DEBUG/TRACE を開ける
-
最新 2.x 系を採用(セキュリティ修正が継続されるため)
6. まとめ
-
log4j2 は “高速+柔軟+安全”。大量ログ・可観測性要件に強い。
-
導入は依存追加 → 設定作成 → 非同期化の3ステップが核。
-
移行は衝突除去と設定変換が肝。SLF4J API で書くと将来の実装差し替えも容易。