Apache Log4j2
Apache財団によるLog4jの後継となる高性能ロギングフレームワーク。ガベージフリーロギング、非同期ロガー、ラムダ式による遅延評価をサポート。ロックフリーデータ構造により低レイテンシシステムに最適化されている。
GitHub概要
apache/logging-log4j2
Apache Log4j is a versatile, feature-rich, efficient logging API and backend for Java.
スター3,538
ウォッチ107
フォーク1,691
作成日:2013年6月12日
言語:Java
ライセンス:Apache License 2.0
トピックス
apacheapijavajvmlibrarylog4jlog4j2loggerloggingsyslog
スター履歴
データ取得日時: 2025/10/22 04:10
ライブラリ
Apache Log4j2
概要
Apache Log4j2は「Apache財団によるLog4jの後継となる高性能ロギングフレームワーク」として開発された、Javaエコシステム最速の先進的ロギングソリューションです。ガベージフリーロギング、非同期ロガー、ラムダ式による遅延評価をサポートし、ロックフリーデータ構造により低レイテンシシステムに最適化。プラグインアーキテクチャによる拡張性と、API・実装の分離設計により、エンタープライズアプリケーションでの地位を確立しています。
詳細
Apache Log4j2 2025年版は最速で最も先進的なJavaロギングフレームワークとして評価され、高スループットアプリケーションでの採用が急増中です。ガベージコレクション圧力軽減機能とマルチスレッド処理能力により、エンタープライズシステムでの地位を確立。SLF4J互換性、自動設定リロード、高度なフィルタリング機能を提供し、Log4j 1.xからの大幅な進化を実現。豊富なアペンダー(ファイル、データベース、Kafka、NoSQL等)とレイアウト(JSON、XML、CSV等)により、多様な出力要件に対応可能です。
主な特徴
- ガベージフリーロギング: メモリアロケーション最小化による超低レイテンシ
- 非同期ロガー: ロックフリー構造による高スループット処理
- ラムダ式サポート: パフォーマンス向上のための遅延評価
- プラグインアーキテクチャ: カスタムコンポーネントの柔軟な追加
- 自動設定リロード: ランタイム設定変更の無停止適用
- 高度なフィルタリング: スクリプト、正規表現、レート制限等
メリット・デメリット
メリット
- Java最速のロギング性能とガベージフリー動作による超低レイテンシ
- 非同期処理とマルチスレッド最適化による高スループット実現
- 豊富なアペンダーとレイアウトによる多様な出力先への対応
- プラグインアーキテクチャによる高い拡張性とカスタマイズ性
- 自動設定リロード機能による運用時の柔軟な設定変更
- Apache財団の継続的メンテナンスによる長期サポート保証
デメリット
- 高機能ゆえの設定複雑性と学習コストの増大
- 小規模アプリケーションには過度な機能と依存関係
- ガベージフリー機能の効果的な活用には専門知識が必要
- 他のログフレームワークからの移行コストが高い
- プラグイン開発には深いフレームワーク理解が必要
- 設定ミスによるパフォーマンス劣化のリスク
参考ページ
書き方の例
インストールと基本セットアップ
<!-- Maven依存関係 -->
<dependencies>
<!-- Log4j2 API -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.23.1</version>
</dependency>
<!-- Log4j2 実装 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.23.1</version>
</dependency>
<!-- SLF4J統合(オプション) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.23.1</version>
</dependency>
<!-- 非同期ロガー用 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.4</version>
</dependency>
</dependencies>
// Gradle依存関係
dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.23.1'
implementation 'org.apache.logging.log4j:log4j-core:2.23.1'
implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.23.1'
implementation 'com.lmax:disruptor:3.4.4'
}
基本的なログ出力
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class BasicLoggingExample {
// ロガーの取得(クラス名で自動命名)
private static final Logger logger = LogManager.getLogger(BasicLoggingExample.class);
public static void main(String[] args) {
// 基本的なログレベル別出力
logger.trace("最詳細レベル: メソッド入出力時のトレース");
logger.debug("デバッグ情報: 変数値={}, 状態={}", "test", "active");
logger.info("一般情報: アプリケーション開始");
logger.warn("警告: メモリ使用量が80%を超過 - {}MB", 1200);
logger.error("エラー: データベース接続失敗", new RuntimeException("Connection timeout"));
logger.fatal("致命的エラー: システム停止");
// パラメータ化メッセージ(高効率)
String userId = "user123";
int transactionId = 98765;
logger.info("取引処理完了: ユーザー={}, 取引ID={}, 金額=¥{}",
userId, transactionId, 15000);
// ラムダ式による遅延評価(ログレベルが無効な場合は実行されない)
logger.debug("重い処理結果: {}", () -> expensiveOperation());
// マーカーを使用した分類
org.apache.logging.log4j.Marker marker =
org.apache.logging.log4j.MarkerManager.getMarker("AUDIT");
logger.info(marker, "監査ログ: ユーザー{}がアクション{}を実行", userId, "LOGIN");
}
private static String expensiveOperation() {
// 重い処理のシミュレーション
try {
Thread.sleep(100);
return "計算結果: " + System.currentTimeMillis();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "中断";
}
}
}
XML設定ファイル(log4j2.xml)による高度な設定
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="60">
<Properties>
<!-- 共通設定 -->
<Property name="logPattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property>
<Property name="logDir">logs</Property>
</Properties>
<Appenders>
<!-- コンソールアペンダー -->
<Console name="ConsoleAppender" target="SYSTEM_OUT">
<PatternLayout pattern="${logPattern}" />
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Console>
<!-- ローリングファイルアペンダー -->
<RollingFile name="FileAppender"
fileName="${logDir}/application.log"
filePattern="${logDir}/application-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${logPattern}" />
<Policies>
<!-- 1日または10MBごとにローテーション -->
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
<!-- エラー専用ファイル -->
<RollingFile name="ErrorFileAppender"
fileName="${logDir}/error.log"
filePattern="${logDir}/error-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${logPattern}" />
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<!-- JSON形式ログ -->
<RollingFile name="JsonFileAppender"
fileName="${logDir}/application.json"
filePattern="${logDir}/application-%d{yyyy-MM-dd}-%i.json.gz">
<JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
<!-- 非同期アペンダー(高性能) -->
<AsyncAppender name="AsyncFileAppender" bufferSize="2048">
<AppenderRef ref="FileAppender"/>
<AppenderRef ref="JsonFileAppender"/>
</AsyncAppender>
<!-- SMTP アペンダー(重要なエラー通知) -->
<SMTP name="MailAppender"
subject="[ERROR] アプリケーションエラー"
to="[email protected]"
from="[email protected]"
smtpHost="smtp.example.com"
smtpPort="587"
smtpUsername="[email protected]"
smtpPassword="${env:SMTP_PASSWORD}"
bufferSize="10">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<HtmlLayout title="エラーレポート"/>
</SMTP>
</Appenders>
<Loggers>
<!-- 特定パッケージの詳細ログ -->
<Logger name="com.example.service" level="DEBUG" additivity="false">
<AppenderRef ref="FileAppender"/>
</Logger>
<!-- データベース関連ログ -->
<Logger name="com.example.dao" level="TRACE" additivity="false">
<AppenderRef ref="FileAppender"/>
</Logger>
<!-- フレームワークログ(制限) -->
<Logger name="org.springframework" level="WARN" additivity="false">
<AppenderRef ref="ConsoleAppender"/>
</Logger>
<!-- 非同期ルートロガー -->
<AsyncRoot level="INFO" includeLocation="false">
<AppenderRef ref="ConsoleAppender"/>
<AppenderRef ref="AsyncFileAppender"/>
<AppenderRef ref="ErrorFileAppender"/>
<AppenderRef ref="MailAppender"/>
</AsyncRoot>
</Loggers>
</Configuration>
プログラマティック設定とカスタムアペンダー
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.builder.api.*;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
public class ProgrammaticConfigurationExample {
public static void main(String[] args) {
// プログラマティック設定の作成
Configuration configuration = createConfiguration();
// 設定の適用
LoggerContext context = (LoggerContext) LogManager.getContext(false);
context.setConfiguration(configuration);
context.updateLoggers();
// ロガーの使用
Logger logger = LogManager.getLogger(ProgrammaticConfigurationExample.class);
logger.info("プログラマティック設定によるログ出力");
logger.debug("デバッグ情報: 設定適用成功");
logger.error("エラーテスト: 意図的なエラーメッセージ");
// カスタムアペンダーのテスト
testCustomAppender(logger);
}
private static Configuration createConfiguration() {
ConfigurationBuilder<BuiltConfiguration> builder =
ConfigurationBuilderFactory.newConfigurationBuilder();
// プロパティ設定
builder.setStatusLevel(Level.DEBUG)
.setConfigurationName("ProgrammaticConfig");
// パターンレイアウト設定
LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
.addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n");
// コンソールアペンダー
AppenderComponentBuilder consoleAppender = builder.newAppender("Console", "CONSOLE")
.addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT)
.add(layoutBuilder);
builder.add(consoleAppender);
// ファイルアペンダー
AppenderComponentBuilder fileAppender = builder.newAppender("File", "File")
.addAttribute("fileName", "logs/programmatic.log")
.addAttribute("append", true)
.add(layoutBuilder);
builder.add(fileAppender);
// 非同期アペンダー
AppenderComponentBuilder asyncAppender = builder.newAppender("Async", "Async")
.addAttribute("bufferSize", 1024)
.addComponent(builder.newAppenderRef("File"));
builder.add(asyncAppender);
// ルートロガー設定
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.INFO)
.add(builder.newAppenderRef("Console"))
.add(builder.newAppenderRef("Async"));
builder.add(rootLogger);
// パッケージ別ロガー
LoggerComponentBuilder packageLogger = builder.newLogger("com.example", Level.DEBUG)
.add(builder.newAppenderRef("File"))
.addAttribute("additivity", false);
builder.add(packageLogger);
return builder.build();
}
private static void testCustomAppender(Logger logger) {
// MDC(Mapped Diagnostic Context)の使用
org.apache.logging.log4j.ThreadContext.put("userId", "user123");
org.apache.logging.log4j.ThreadContext.put("sessionId", "session456");
org.apache.logging.log4j.ThreadContext.put("traceId", "trace789");
try {
logger.info("MDC付きログ: ユーザー処理開始");
// 業務処理のシミュレーション
processUserData();
logger.info("MDC付きログ: ユーザー処理完了");
} finally {
// MDCのクリア
org.apache.logging.log4j.ThreadContext.clearAll();
}
}
private static void processUserData() {
Logger logger = LogManager.getLogger("com.example.service.UserService");
logger.debug("ユーザーデータ取得開始");
try {
// 処理のシミュレーション
Thread.sleep(100);
logger.info("ユーザーデータ取得成功: レコード数={}", 150);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("ユーザーデータ取得中断", e);
}
}
}
非同期ロギングとパフォーマンス最適化
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ObjectMessage;
import org.apache.logging.log4j.message.StringFormattedMessage;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class HighPerformanceLoggingExample {
private static final Logger logger = LogManager.getLogger(HighPerformanceLoggingExample.class);
public static void main(String[] args) throws InterruptedException {
// パフォーマンステスト
performanceTest();
// 構造化ログテスト
structuredLoggingTest();
// マルチスレッドテスト
multiThreadTest();
// ガベージフリーロギングテスト
garbageFreeLoggingTest();
}
private static void performanceTest() {
logger.info("パフォーマンステスト開始");
long startTime = System.nanoTime();
int logCount = 100000;
for (int i = 0; i < logCount; i++) {
// 高速ログ出力(パラメータ化メッセージ)
logger.info("パフォーマンステスト: 番号={}, タイムスタンプ={}",
i, System.currentTimeMillis());
if (i % 10000 == 0) {
long currentTime = System.nanoTime();
double elapsedMs = (currentTime - startTime) / 1_000_000.0;
logger.debug("進捗: {}/{}, 経過時間={}ms, スループット={} logs/sec",
i, logCount, elapsedMs, (i * 1000.0 / elapsedMs));
}
}
long endTime = System.nanoTime();
double totalMs = (endTime - startTime) / 1_000_000.0;
double throughput = logCount * 1000.0 / totalMs;
logger.info("パフォーマンステスト完了: 総時間={}ms, スループット={} logs/sec",
totalMs, throughput);
}
private static void structuredLoggingTest() {
logger.info("構造化ログテスト開始");
// Map型オブジェクトによる構造化ログ
Map<String, Object> logData = new HashMap<>();
logData.put("userId", "user123");
logData.put("action", "purchase");
logData.put("productId", "prod456");
logData.put("amount", 15000);
logData.put("timestamp", System.currentTimeMillis());
logger.info(new ObjectMessage(logData));
// カスタムオブジェクトによる構造化ログ
UserTransaction transaction = new UserTransaction("user789", "sale", 25000);
logger.info("取引ログ: {}", transaction);
// JSON風の構造化ログ
logger.info("API呼び出し: {\"endpoint\":\"/api/users\", \"method\":\"GET\", \"responseTime\":{}}", 150);
}
private static void multiThreadTest() throws InterruptedException {
logger.info("マルチスレッドテスト開始");
ExecutorService executor = Executors.newFixedThreadPool(10);
int tasksPerThread = 1000;
for (int threadId = 0; threadId < 10; threadId++) {
final int finalThreadId = threadId;
executor.submit(() -> {
for (int i = 0; i < tasksPerThread; i++) {
logger.info("スレッド{}: タスク番号={}, 実行時刻={}",
finalThreadId, i, System.currentTimeMillis());
if (i % 100 == 0) {
logger.debug("スレッド{}: 進捗={}%", finalThreadId,
(i * 100 / tasksPerThread));
}
}
logger.info("スレッド{}: 全タスク完了", finalThreadId);
});
}
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);
logger.info("マルチスレッドテスト完了");
}
private static void garbageFreeLoggingTest() {
logger.info("ガベージフリーロギングテスト開始");
// プリミティブ型のログ(アロケーション最小)
long startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
for (int i = 0; i < 10000; i++) {
// ガベージフリー対応の書き方
logger.info("GCフリーテスト: 反復回数={}", i);
}
// GC実行
System.gc();
Thread.yield();
long endMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
logger.info("メモリ使用量: 開始={}KB, 終了={}KB, 差分={}KB",
startMemory/1024, endMemory/1024, (endMemory-startMemory)/1024);
logger.info("ガベージフリーロギングテスト完了");
}
// ユーザー取引データクラス
static class UserTransaction {
private final String userId;
private final String action;
private final int amount;
private final long timestamp;
public UserTransaction(String userId, String action, int amount) {
this.userId = userId;
this.action = action;
this.amount = amount;
this.timestamp = System.currentTimeMillis();
}
@Override
public String toString() {
return String.format("{\"userId\":\"%s\", \"action\":\"%s\", \"amount\":%d, \"timestamp\":%d}",
userId, action, amount, timestamp);
}
}
}
Spring Boot統合とプロダクション設定
// Spring Boot設定クラス
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.UUID;
@SpringBootApplication
public class Log4j2SpringBootApplication {
private static final Logger logger = LogManager.getLogger(Log4j2SpringBootApplication.class);
public static void main(String[] args) {
logger.info("Spring Boot アプリケーション開始");
SpringApplication.run(Log4j2SpringBootApplication.class, args);
logger.info("Spring Boot アプリケーション開始完了");
}
}
@RestController
@RequestMapping("/api")
class ApiController {
private static final Logger logger = LogManager.getLogger(ApiController.class);
@GetMapping("/users/{userId}")
public ResponseEntity<UserResponse> getUser(@PathVariable String userId,
HttpServletRequest request) {
// リクエストIDの生成と設定
String requestId = UUID.randomUUID().toString();
org.apache.logging.log4j.ThreadContext.put("requestId", requestId);
org.apache.logging.log4j.ThreadContext.put("userId", userId);
try {
logger.info("ユーザー取得リクエスト: URL={}, IP={}, UserAgent={}",
request.getRequestURL(),
request.getRemoteAddr(),
request.getHeader("User-Agent"));
// ビジネスロジック実行
UserResponse user = userService.findUser(userId);
logger.info("ユーザー取得成功: ユーザー名={}", user.getName());
return ResponseEntity.ok(user);
} catch (UserNotFoundException e) {
logger.warn("ユーザーが見つかりません: userId={}", userId, e);
return ResponseEntity.notFound().build();
} catch (Exception e) {
logger.error("ユーザー取得エラー: userId={}", userId, e);
return ResponseEntity.status(500).build();
} finally {
// ThreadContext のクリア
org.apache.logging.log4j.ThreadContext.clearAll();
}
}
@PostMapping("/users")
public ResponseEntity<UserResponse> createUser(@RequestBody CreateUserRequest request,
HttpServletRequest httpRequest) {
String requestId = UUID.randomUUID().toString();
org.apache.logging.log4j.ThreadContext.put("requestId", requestId);
try {
logger.info("ユーザー作成リクエスト: 名前={}, メール={}",
request.getName(), request.getEmail());
// バリデーション
if (request.getName() == null || request.getName().trim().isEmpty()) {
logger.warn("ユーザー作成失敗: 名前が空");
return ResponseEntity.badRequest().build();
}
// ユーザー作成
UserResponse user = userService.createUser(request);
logger.info("ユーザー作成成功: ID={}, 名前={}", user.getId(), user.getName());
return ResponseEntity.status(201).body(user);
} catch (EmailDuplicateException e) {
logger.warn("メールアドレス重複: メール={}", request.getEmail(), e);
return ResponseEntity.status(409).build();
} catch (Exception e) {
logger.error("ユーザー作成エラー", e);
return ResponseEntity.status(500).build();
} finally {
org.apache.logging.log4j.ThreadContext.clearAll();
}
}
}
// ログ設定用プロファイル(application-production.yml)
/*
logging:
config: classpath:log4j2-production.xml
level:
com.example: INFO
org.springframework: WARN
org.hibernate: WARN
# システムプロパティ設定
log4j2:
asyncLoggerWaitStrategy: Block
asyncLoggerRingBufferSize: 2048
garbageFreeThresholdBytes: 1024
enableThreadLocals: true
*/
<!-- log4j2-production.xml(本番環境用設定) -->
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="300">
<Properties>
<Property name="appName">MySpringBootApp</Property>
<Property name="logPattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%X{requestId}] %logger{36} - %msg%n</Property>
<Property name="logDir">/var/log/${appName}</Property>
</Properties>
<Appenders>
<!-- アプリケーションログ -->
<RollingFile name="AppFileAppender"
fileName="${logDir}/application.log"
filePattern="${logDir}/application-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${logPattern}" />
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="90"/>
</RollingFile>
<!-- エラーログ -->
<RollingFile name="ErrorFileAppender"
fileName="${logDir}/error.log"
filePattern="${logDir}/error-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${logPattern}" />
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="50MB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingFile>
<!-- アクセスログ -->
<RollingFile name="AccessFileAppender"
fileName="${logDir}/access.log"
filePattern="${logDir}/access-%d{yyyy-MM-dd}-%i.log.gz">
<JsonTemplateLayout eventTemplateUri="classpath:AccessLogLayout.json"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="90"/>
</RollingFile>
<!-- 非同期ラッパー -->
<AsyncAppender name="AsyncAppender" bufferSize="4096"
shutdownTimeout="3000" includeLocation="false">
<AppenderRef ref="AppFileAppender"/>
</AsyncAppender>
</Appenders>
<Loggers>
<!-- アプリケーションロガー -->
<Logger name="com.example" level="INFO" additivity="false">
<AppenderRef ref="AsyncAppender"/>
<AppenderRef ref="ErrorFileAppender"/>
</Logger>
<!-- アクセスログロガー -->
<Logger name="ACCESS_LOG" level="INFO" additivity="false">
<AppenderRef ref="AccessFileAppender"/>
</Logger>
<!-- フレームワークログ制限 -->
<Logger name="org.springframework" level="WARN" additivity="false">
<AppenderRef ref="AsyncAppender"/>
</Logger>
<!-- 非同期ルートロガー -->
<AsyncRoot level="INFO" includeLocation="false">
<AppenderRef ref="AsyncAppender"/>
<AppenderRef ref="ErrorFileAppender"/>
</AsyncRoot>
</Loggers>
</Configuration>