首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Log4j2 無配置文件動態創建 Logger:每個任務獨立日志文件實戰

     編輯:Java 綜合教學

場景痛點

傳統 log4j2.xml 靜態配置無法滿足「每個任務/用戶/業務單獨日志文件」需求(如 job.001.log、job.002.log)。需運行時動態創建 Logger、Appender、Layout。

核心組件關係

  • LoggerContext:日志上下文容器,可多實例(LogManager.getContext(false))
  • Configuration:持有所有 Appender、LoggerConfig、Filter
  • LoggerConfig:Logger 配置,關聯 AppenderRef、Level、Filter
  • Appender:輸出目的地(FileAppender、RollingFileAppender 等)
  • Layout:格式化器(PatternLayout 等)

動態創建完整代碼

public class JobLogFactory {
    private JobLogFactory() {}

    public static void start(int jobId) {
        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        Configuration config = ctx.getConfiguration();

        // 1. Layout
        Layout layout = PatternLayout.createLayout(
            PatternLayout.DEFAULT_CONVERSION_PATTERN, config, null, null, true, false, null, null);

        // 2. FileAppender
        String fileName = String.format("logs/test/syncshows-job-%s.log", jobId);
        Appender appender = FileAppender.createAppender(
            fileName, "true", "false", "" + jobId, null, "true", "true", null, layout, null, null, null, config);
        appender.start();
        config.addAppender(appender);

        // 3. LoggerConfig
        AppenderRef ref = AppenderRef.createAppenderRef("" + jobId, null, null);
        LoggerConfig loggerConfig = LoggerConfig.createLogger(
            "false", Level.ALL, "" + jobId, "true", new AppenderRef[]{ref}, null, config, null);
        loggerConfig.addAppender(appender, null, null);
        config.addLogger("" + jobId, loggerConfig);

        // 4. 更新生效
        ctx.updateLoggers();
    }

    public static void stop(int jobId) {
        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        Configuration config = ctx.getConfiguration();
        config.getAppender("" + jobId).stop();
        config.getLoggerConfig("" + jobId).removeAppender("" + jobId);
        config.removeLogger("" + jobId);
        ctx.updateLoggers();
    }

    public static Logger createLogger(int jobId) {
        start(jobId);
        return LoggerFactory.getLogger("" + jobId);  // SLF4J 橋接
    }
}

測試驗證

for (int i = 0; i < 50000; i++) {
    Logger logger = JobLogFactory.createLogger(i);
    logger.info("Testing {}", i);
    JobLogFactory.stop(i);  // 必須釋放,否則文件句柄耗盡
}

關鍵注意點

  • 必須調用 stop() 釋放資源,否則大量 Logger 導致 Too many open files
  • LogManager.getContext(false) 獲取非單例上下文,隔離不同任務配置
  • 生產環境建議用 RollingFileAppender + 基於大小/時間滾動策略
  • Log4j 2.3+ 驗證通過,低版本 API 可能不同

架構圖

Log4j2架構

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved