SLF4J + Logback

JavaとKotlinで人気のロギング組み合わせ。SLF4Jファサードとlogback実装の組み合わせにより、柔軟性と性能のバランスを実現。既存のJavaエコシステムとの完全互換性を保持し、エンタープライズ環境で信頼性が高い。

ロギングJavaSLF4JLogback統合エンタープライズ

ライブラリ

SLF4J + Logback

概要

SLF4J + Logbackは「Java エンタープライズ向けの最強ロギングコンビネーション」として確立された、Javaアプリケーションにおける事実上の標準ロギングソリューションです。SLF4J(Simple Logging Facade for Java)の統一APIとLogbackの高性能実装を組み合わせることで、シンプルな開発体験と本格的なエンタープライズ機能を両立。Spring Boot、Spring Framework、Hibernate等の主要フレームワークでデフォルト採用され、設定の柔軟性、高いパフォーマンス、豊富な出力オプション、自動リロード機能などにより、小規模開発から大規模エンタープライズシステムまで幅広く対応可能な包括的ロギングソリューションです。

詳細

SLF4J + Logback 2025年版は Java エンタープライズロギングの決定版として成熟を極めています。両ライブラリは同一開発者(Ceki Gülcü)により設計されているため完璧な統合性を誇り、SLF4JのシンプルなAPIとLogbackの高度な機能が seamlessly 連携。XML、Groovy、プログラムによる柔軟な設定システム、時間・サイズベースのファイルローテーション、非同期ロギング、フィルタリング、条件分岐ロジック、JMX統合、ステータス管理システムなど企業レベルの要件を完全網羅。MDC(Mapped Diagnostic Context)による分散トレーシング対応、マーカーベースの高度なログ分類、構造化ログ対応、自動設定監視・リロード機能により、DevOps環境での運用効率を最大化します。

主な特徴

  • 完璧な統合性: 同一設計者による最適化された組み合わせ
  • 高性能非同期ロギング: AsyncAppenderによる高スループット実現
  • 柔軟な設定システム: XML/Groovy/プログラム設定と自動リロード
  • 豊富なAppender: Console、File、RollingFile、DB、JMS、メール等
  • 高度なフィルタリング: 条件ベースの動的ログ制御
  • エンタープライズ機能: JMX統合、ステータス管理、設定検証

メリット・デメリット

メリット

  • Java エコシステムでの圧倒的な普及率と成熟した実装品質
  • SLF4J API の柔軟性とLogback実装の高性能を同時享受
  • Spring Boot等の主要フレームワークでのゼロ設定統合
  • XML/Groovy/プログラムによる設定の柔軟性と自動リロード
  • 非同期ロギングによる高いパフォーマンスとスループット
  • 豊富なAppenderとLayoutによる多様な出力オプション
  • 企業環境に必要なセキュリティ、監査、運用機能の完備

デメリット

  • 高機能ゆえの初期設定の複雑さと学習コストの高さ
  • XML設定ファイルの肥大化と可読性低下の可能性
  • 豊富な機能による設定ミスのリスクと効果的な設定の困難さ
  • メモリ使用量が単純なロギングライブラリより多い
  • 非同期ロギング時のログ順序保証とメモリ管理の考慮必要
  • 設定の複雑性により問題発生時のトラブルシューティング困難

参考ページ

書き方の例

インストール・セットアップ

<!-- Maven依存関係(Spring Boot使用時は自動含有) -->
<dependencies>
  <!-- SLF4J API -->
  <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.17</version>
  </dependency>
  
  <!-- Logback Classic(SLF4J実装) -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.5.18</version>
  </dependency>
  
  <!-- Logback Core(Classic に含まれるが明示的に指定) -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.5.18</version>
  </dependency>
  
  <!-- 高度な機能(オプション) -->
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-access</artifactId>
    <version>1.5.18</version>
  </dependency>
  
  <!-- JSON形式ログ出力(オプション) -->
  <dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>8.0</version>
  </dependency>
</dependencies>
// Gradle依存関係
dependencies {
    // SLF4J + Logback
    implementation 'org.slf4j:slf4j-api:2.0.17'
    implementation 'ch.qos.logback:logback-classic:1.5.18'
    
    // 追加機能
    implementation 'ch.qos.logback:logback-access:1.5.18'
    implementation 'net.logstash.logback:logstash-logback-encoder:8.0'
}

基本的なログ出力

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

public class EnterpriseLoggingService {
    private static final Logger logger = LoggerFactory.getLogger(EnterpriseLoggingService.class);
    
    // マーカー定義
    private static final Marker AUDIT_MARKER = MarkerFactory.getMarker("AUDIT");
    private static final Marker BUSINESS_MARKER = MarkerFactory.getMarker("BUSINESS");
    private static final Marker SECURITY_MARKER = MarkerFactory.getMarker("SECURITY");
    
    public void processBusinessTransaction(String transactionId, String userId, double amount) {
        // MDCに文脈情報を設定
        MDC.put("transactionId", transactionId);
        MDC.put("userId", userId);
        MDC.put("amount", String.valueOf(amount));
        MDC.put("requestId", generateRequestId());
        
        try {
            logger.info(BUSINESS_MARKER, "ビジネストランザクション開始: transactionId={}", transactionId);
            
            // セキュリティチェック
            if (amount > 100000) {
                logger.warn(SECURITY_MARKER, "高額取引が検出されました: amount={}, userId={}", amount, userId);
            }
            
            // 監査ログ
            logger.info(AUDIT_MARKER, "取引承認: transactionId={}, userId={}, amount={}", 
                transactionId, userId, amount);
            
            // ビジネスロジック実行
            validateTransaction(transactionId, userId, amount);
            executeTransaction(transactionId, amount);
            recordTransaction(transactionId);
            
            logger.info(BUSINESS_MARKER, "ビジネストランザクション完了: transactionId={}", transactionId);
            logger.info(AUDIT_MARKER, "取引完了: transactionId={}, status=SUCCESS", transactionId);
            
        } catch (ValidationException e) {
            logger.warn(BUSINESS_MARKER, "トランザクション検証エラー: {}", e.getMessage());
            logger.warn(AUDIT_MARKER, "取引拒否: transactionId={}, reason={}", transactionId, e.getMessage());
            throw e;
        } catch (Exception e) {
            logger.error(BUSINESS_MARKER, "トランザクション処理エラー: transactionId={}", transactionId, e);
            logger.error(AUDIT_MARKER, "取引エラー: transactionId={}, error={}", transactionId, e.getMessage());
            throw new TransactionException("取引処理に失敗しました", e);
        } finally {
            // MDCクリア
            MDC.clear();
        }
    }
    
    // 構造化ログの活用例
    public void generateDetailedReport(String reportType, Map<String, Object> parameters) {
        MDC.put("reportType", reportType);
        MDC.put("reportId", generateReportId());
        
        try {
            logger.info("レポート生成開始: type={}", reportType);
            
            // パラメータの詳細ログ
            if (logger.isDebugEnabled()) {
                logger.debug("レポートパラメータ:");
                parameters.forEach((key, value) -> 
                    logger.debug("  {}={}", key, value));
            }
            
            long startTime = System.currentTimeMillis();
            
            // レポート生成処理
            generateReport(reportType, parameters);
            
            long duration = System.currentTimeMillis() - startTime;
            
            // パフォーマンスログ
            if (duration > 5000) {
                logger.warn("レポート生成が遅延: type={}, duration={}ms", reportType, duration);
            } else {
                logger.info("レポート生成完了: type={}, duration={}ms", reportType, duration);
            }
            
        } finally {
            MDC.clear();
        }
    }
    
    private String generateRequestId() {
        return "req_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
    }
    
    private String generateReportId() {
        return "rpt_" + System.currentTimeMillis();
    }
    
    private void validateTransaction(String transactionId, String userId, double amount) {
        // 検証ロジック
    }
    
    private void executeTransaction(String transactionId, double amount) {
        // 実行ロジック
    }
    
    private void recordTransaction(String transactionId) {
        // 記録ロジック
    }
    
    private void generateReport(String reportType, Map<String, Object> parameters) {
        // レポート生成ロジック
    }
}

ログレベル設定

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogbackConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(LogbackConfiguration.class);
    
    // プログラムによるログレベル変更
    public static void changeLogLevel(String loggerName, Level level) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        ch.qos.logback.classic.Logger targetLogger = loggerContext.getLogger(loggerName);
        
        Level oldLevel = targetLogger.getLevel();
        targetLogger.setLevel(level);
        
        logger.info("ログレベル変更: logger={}, {} -> {}", loggerName, oldLevel, level);
    }
    
    // ルートロガーレベル変更
    public static void changeRootLogLevel(Level level) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        ch.qos.logback.classic.Logger rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
        
        Level oldLevel = rootLogger.getLevel();
        rootLogger.setLevel(level);
        
        logger.info("ルートログレベル変更: {} -> {}", oldLevel, level);
    }
    
    // 動的設定リロード
    public static void reloadConfiguration(String configFile) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        
        try {
            JoranConfigurator configurator = new JoranConfigurator();
            configurator.setContext(loggerContext);
            
            // 既存設定をクリア
            loggerContext.reset();
            
            // 新しい設定をロード
            configurator.doConfigure(configFile);
            
            logger.info("ログ設定を再読み込みしました: {}", configFile);
            
        } catch (JoranException e) {
            logger.error("ログ設定の再読み込みに失敗しました: {}", e.getMessage(), e);
        }
    }
    
    // ログレベルの一括確認
    public static void checkAllLogLevels() {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        
        logger.info("現在のログレベル設定一覧:");
        
        // ルートロガー
        ch.qos.logback.classic.Logger rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
        logger.info("ROOT: {}", rootLogger.getLevel());
        
        // 全ロガーの確認
        loggerContext.getLoggerList().stream()
            .filter(log -> log.getLevel() != null)
            .forEach(log -> logger.info("{}: {}", log.getName(), log.getLevel()));
    }
}

構造化ログ

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import net.logstash.logback.argument.StructuredArguments;
import net.logstash.logback.marker.Markers;

import java.util.Map;
import java.util.HashMap;

public class StructuredLoggingWithLogback {
    private static final Logger logger = LoggerFactory.getLogger(StructuredLoggingWithLogback.class);
    
    // JSON構造化ログの例(Logstash Encoderを使用)
    public void structuredApiLogging(String endpoint, String method, int statusCode, long responseTime) {
        // MDCによる文脈情報
        MDC.put("service", "user-api");
        MDC.put("version", "1.2.0");
        MDC.put("environment", "production");
        
        try {
            // 構造化された追加情報
            Map<String, Object> requestDetails = new HashMap<>();
            requestDetails.put("endpoint", endpoint);
            requestDetails.put("method", method);
            requestDetails.put("statusCode", statusCode);
            requestDetails.put("responseTimeMs", responseTime);
            requestDetails.put("timestamp", System.currentTimeMillis());
            
            // StructuredArgumentsを使用したJSON出力
            if (statusCode >= 400) {
                logger.warn("API エラーレスポンス: {}", 
                    StructuredArguments.entries(requestDetails));
            } else if (responseTime > 1000) {
                logger.warn("API 応答遅延: {}", 
                    StructuredArguments.entries(requestDetails));
            } else {
                logger.info("API リクエスト処理完了: {}", 
                    StructuredArguments.entries(requestDetails));
            }
            
            // マーカーを使用した分類
            if (statusCode >= 500) {
                logger.error(Markers.append("alertType", "server_error"), 
                    "サーバーエラーが発生: endpoint={}, statusCode={}", endpoint, statusCode);
            }
            
        } finally {
            MDC.clear();
        }
    }
    
    // 複雑な業務データの構造化ログ
    public void businessEventLogging(String eventType, Object eventData) {
        MDC.put("eventType", eventType);
        MDC.put("eventId", generateEventId());
        
        try {
            // イベントデータを構造化形式で記録
            logger.info("ビジネスイベント発生: eventType={}, data={}", 
                eventType,
                StructuredArguments.value("eventData", eventData));
            
            // 特定の業務イベントの詳細ログ
            if ("ORDER_CREATED".equals(eventType)) {
                Map<String, Object> orderDetails = extractOrderDetails(eventData);
                logger.info("注文作成イベント詳細: {}", 
                    StructuredArguments.entries(orderDetails));
            }
            
        } finally {
            MDC.clear();
        }
    }
    
    // パフォーマンス監視ログ
    public void performanceLogging(String operationName, long duration, Map<String, Object> metrics) {
        MDC.put("operation", operationName);
        
        try {
            Map<String, Object> perfData = new HashMap<>(metrics);
            perfData.put("duration_ms", duration);
            perfData.put("timestamp", System.currentTimeMillis());
            
            // パフォーマンス閾値による分類
            if (duration > 5000) {
                logger.error(Markers.append("alertType", "performance_critical"),
                    "重大なパフォーマンス問題: operation={}, metrics={}", 
                    operationName, StructuredArguments.entries(perfData));
            } else if (duration > 1000) {
                logger.warn(Markers.append("alertType", "performance_warning"),
                    "パフォーマンス警告: operation={}, metrics={}", 
                    operationName, StructuredArguments.entries(perfData));
            } else {
                logger.debug("パフォーマンス記録: operation={}, metrics={}", 
                    operationName, StructuredArguments.entries(perfData));
            }
            
        } finally {
            MDC.clear();
        }
    }
    
    private String generateEventId() {
        return "evt_" + System.currentTimeMillis() + "_" + 
               Integer.toHexString((int)(Math.random() * 0xFFFF));
    }
    
    private Map<String, Object> extractOrderDetails(Object eventData) {
        // イベントデータから注文詳細を抽出
        Map<String, Object> details = new HashMap<>();
        details.put("orderId", "12345");
        details.put("customerId", "user123");
        details.put("amount", 999.99);
        return details;
    }
}

設定ファイル例

<!-- logback-spring.xml (Spring Boot推奨) -->
<configuration debug="false" scan="true" scanPeriod="30 seconds">
    <!-- プロパティ定義 -->
    <property name="LOG_HOME" value="logs" />
    <property name="APP_NAME" value="myapp" />
    <property name="PATTERN_CONSOLE" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{requestId}] %logger{36} - %msg%n" />
    <property name="PATTERN_FILE" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{userId}:%X{requestId}] %logger{36} - %msg%n" />
    
    <!-- コンソールAppender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${PATTERN_CONSOLE}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 一般ファイルAppender(ローリング) -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${APP_NAME}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/${APP_NAME}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>${PATTERN_FILE}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- エラー専用ファイルAppender -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${APP_NAME}-error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/${APP_NAME}-error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${PATTERN_FILE}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    
    <!-- 非同期Appender(パフォーマンス向上) -->
    <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
        <queueSize>1024</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <maxFlushTime>5000</maxFlushTime>
        <includeCallerData>false</includeCallerData>
    </appender>
    
    <!-- JSON形式ログAppender -->
    <appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/${APP_NAME}-json.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/${APP_NAME}-json.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp />
                <version />
                <logLevel />
                <message />
                <mdc />
                <arguments />
                <stackTrace />
            </providers>
        </encoder>
    </appender>
    
    <!-- 監査ログ専用Appender -->
    <appender name="AUDIT_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/audit.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/audit.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>365</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{userId}:%X{sessionId}] %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator>
                <expression>marker != null && marker.contains("AUDIT")</expression>
            </evaluator>
            <onMismatch>DENY</onMismatch>
            <onMatch>ACCEPT</onMatch>
        </filter>
    </appender>
    
    <!-- 環境別設定 -->
    <springProfile name="development">
        <logger name="com.example" level="DEBUG" />
        <logger name="org.springframework.web" level="DEBUG" />
        <root level="DEBUG">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="FILE" />
        </root>
    </springProfile>
    
    <springProfile name="production">
        <logger name="com.example" level="INFO" />
        <logger name="org.springframework" level="WARN" />
        <logger name="org.hibernate" level="WARN" />
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="ASYNC_FILE" />
            <appender-ref ref="ERROR_FILE" />
            <appender-ref ref="JSON_FILE" />
            <appender-ref ref="AUDIT_FILE" />
        </root>
    </springProfile>
    
    <!-- ステータス管理 -->
    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
</configuration>

パフォーマンス最適化

import ch.qos.logback.classic.AsyncAppender;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import org.slf4j.LoggerFactory;

public class LogbackPerformanceOptimization {
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(LogbackPerformanceOptimization.class);
    
    // 非同期Appenderの動的設定
    public static void setupAsyncAppender(String loggerName, String targetAppenderName) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger targetLogger = loggerContext.getLogger(loggerName);
        
        // 既存のAppenderを取得
        Appender<ILoggingEvent> targetAppender = targetLogger.getAppender(targetAppenderName);
        if (targetAppender == null) {
            logger.warn("対象Appenderが見つかりません: {}", targetAppenderName);
            return;
        }
        
        // 非同期Appenderを作成
        AsyncAppender asyncAppender = new AsyncAppender();
        asyncAppender.setContext(loggerContext);
        asyncAppender.setName("ASYNC_" + targetAppenderName);
        
        // パフォーマンス最適化設定
        asyncAppender.setQueueSize(1024);           // キューサイズ
        asyncAppender.setDiscardingThreshold(0);    // 破棄閾値(0=破棄しない)
        asyncAppender.setMaxFlushTime(5000);        // 最大フラッシュ時間
        asyncAppender.setIncludeCallerData(false);  // 呼び出し元情報を含めない(高速化)
        asyncAppender.setNeverBlock(true);          // ノンブロッキング
        
        // 対象Appenderを追加
        asyncAppender.addAppender(targetAppender);
        asyncAppender.start();
        
        // ロガーから元のAppenderを削除し、非同期Appenderを追加
        targetLogger.detachAppender(targetAppender);
        targetLogger.addAppender(asyncAppender);
        
        logger.info("非同期Appenderを設定しました: logger={}, appender={}", loggerName, targetAppenderName);
    }
    
    // 大量ログ処理の最適化
    public static void optimizedBulkLogging(List<String> dataList) {
        logger.info("大量データ処理開始: {} 件", dataList.size());
        
        int batchSize = 1000;
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < dataList.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, dataList.size());
            List<String> batch = dataList.subList(i, endIndex);
            
            // バッチレベルでのログ出力(個別項目ログは避ける)
            if (logger.isDebugEnabled()) {
                logger.debug("バッチ処理: [{}-{}] / {}", i + 1, endIndex, dataList.size());
            }
            
            // 実際の処理
            processBatch(batch);
            
            // 進捗ログ(間引き)
            if ((i / batchSize) % 10 == 0) {
                long currentTime = System.currentTimeMillis();
                double avgTimePerBatch = (currentTime - startTime) / (double)(i / batchSize + 1);
                logger.info("処理進捗: {}/{} バッチ完了 (平均 {:.2f}ms/バッチ)", 
                    (i / batchSize + 1), (dataList.size() + batchSize - 1) / batchSize, avgTimePerBatch);
            }
        }
        
        long totalTime = System.currentTimeMillis() - startTime;
        logger.info("大量データ処理完了: {} 件, 総時間: {}ms", dataList.size(), totalTime);
    }
    
    // メモリ効率的なログ文字列生成
    private static final ThreadLocal<StringBuilder> LOG_BUFFER = 
        ThreadLocal.withInitial(() -> new StringBuilder(512));
    
    public static void memoryEfficientLogging(Map<String, Object> largeDataMap) {
        if (!logger.isDebugEnabled()) {
            return;
        }
        
        StringBuilder buffer = LOG_BUFFER.get();
        buffer.setLength(0);  // クリア
        
        buffer.append("Large data summary: ");
        int count = 0;
        for (Map.Entry<String, Object> entry : largeDataMap.entrySet()) {
            if (count > 0) buffer.append(", ");
            buffer.append(entry.getKey()).append("=").append(entry.getValue());
            
            // 大きすぎる場合は省略
            if (++count >= 10) {
                buffer.append(", ... (").append(largeDataMap.size() - 10).append(" more)");
                break;
            }
        }
        
        logger.debug(buffer.toString());
    }
    
    // 条件付きログの最適化
    public static void conditionalLogging(String operation, Object data, boolean isHighPriority) {
        // 高優先度または特定の条件でのみ詳細ログ
        if (isHighPriority || logger.isTraceEnabled()) {
            logger.info("詳細操作ログ: operation={}, data={}", operation, data);
        } else {
            // 通常は簡略ログ
            logger.debug("操作実行: {}", operation);
        }
    }
    
    // ログ設定の動的調整
    public static void adjustLoggingForPerformance(boolean highPerformanceMode) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        
        if (highPerformanceMode) {
            // 高性能モード: ログレベルを上げ、詳細ログを抑制
            loggerContext.getLogger("com.example.detailed").setLevel(ch.qos.logback.classic.Level.WARN);
            loggerContext.getLogger("org.springframework").setLevel(ch.qos.logback.classic.Level.ERROR);
            logger.info("高性能モードに切り替えました");
        } else {
            // 通常モード: 詳細ログを有効化
            loggerContext.getLogger("com.example.detailed").setLevel(ch.qos.logback.classic.Level.DEBUG);
            loggerContext.getLogger("org.springframework").setLevel(ch.qos.logback.classic.Level.WARN);
            logger.info("通常モードに切り替えました");
        }
    }
    
    private static void processBatch(List<String> batch) {
        // バッチ処理の実装
        try {
            Thread.sleep(10);  // 処理時間の模擬
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}