创建自定义 log4j2 滚动文件附加程序

create a custom log4j2 rolling file appender

我想创建一个自定义的 log4j2 滚动文件追加器。我需要创建这个自定义附加程序,因为我想用当前线程名称包装文件名。我们正在尝试将 log4j 1.x 迁移到最新的 log4j2 版本,之前我们使用 DailyRollingFileAppender 来记录我们应用程序的所有活动。

请找到下面的代码。

在这里,我们尝试借助基于 threadName 的 DailyRollingFileAppender 每天将日志附加到文件中。

由于 DailyRollingFileAppender 在最新版本中已被弃用 - 因此,如何结合我们基于线程的逻辑来创建自定义滚动文件附加程序。?

找到下面的 log4j.properties 文件

log4j.logger.***=INFO, FileLogger
# log4j.appender.FileLogger=org.apache.log4j.DailyRollingFileAppender
# Custom Appendar which will redirect the logs based on thread names configured using 
# log4j.appender.FileLogger.threadNameMapping property below
log4j.appender.FileLogger=********.framework.log4j.appender.ThreadNamePatternAppender 
log4j.appender.FileLogger.DatePattern='.'yyyy-MM-dd
log4j.appender.FileLogger.file=/logs/fileName.log
log4j.appender.FileLogger.layout=org.apache.log4j.PatternLayout
log4j.appender.FileLogger.layout.ConversionPattern=%d [%-5p] [%t] [%c{1}] [%M] - %m%n
# Custom property to hold mapping between thread names and log file for plug-in
# Beware - ThreadNamePatternAppender class inherits DailyRollingFileAppender hence it will not work for any other type of appender
# This can be distuingished using - ThreadName1>ThreadName1.log|ThreadName2>ThreadName2.log|.....|ThreadNameN>ThreadNameN.log
# Note - If there is no mapping for a particular thread then logs will be written to default log file
log4j.appender.FileLogger.threadNameMapping=********/logs/fileName-fileName.log

谢谢!

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

import org.apache.logging.log4j.core.appender.RollingFileAppender;

import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;


public class ThreadNamePatternAppender extends DailyRollingFileAppender {
    private Map<String, DailyRollingFileAppender> threadBasedSubAppenders = new HashMap<String, DailyRollingFileAppender>();
    private String threadNameMapping;

    public String getThreadNameMapping() {
        return threadNameMapping;
    }

    public void setThreadNameMapping(String threadNameMapping) {
        this.threadNameMapping = threadNameMapping;
    }

    @Override
    public void activateOptions() {
        super.activateOptions();
        if (threadNameMapping != null && threadNameMapping.trim().length() > 0) {
            DailyRollingFileAppender tempAppender;
            String[] threadNames = threadNameMapping.split("\|");
            for (String threadName : threadNames) {
                if (threadName != null && threadName.length() > 0) {
                    try {
                        LogLog.debug(String.format("Creating new appender for thread %s", threadName));
                        tempAppender = new DailyRollingFileAppender(getLayout(), threadName.split(">")[1],
                                getDatePattern());
                        threadBasedSubAppenders.put(threadName.split(">")[0], tempAppender);
                    } catch (Exception ex) {
                        LogLog.error("Failed to create appender", ex);
                    }
                }
            }
        }
    }

    @Override
    public void append(LoggingEvent event) {
        String threadName = event.getThreadName().split(" ")[0];
        if (threadBasedSubAppenders.containsKey(threadName)) {
            threadBasedSubAppenders.get(threadName).append(event);
        } else {
            super.append(event);
        }
    }

    @Override
    public synchronized void close() {
        LogLog.debug("Calling Close on ThreadNamePatternAppender" + getName());
        for (DailyRollingFileAppender appender : threadBasedSubAppenders.values()) {
            appender.close();
        }
        this.closed = true;
    }
}



  

Log4j中的RollingFileAppender2.x是final,所以不能扩展。但是,您可以使用以下方法获得自定义 Log4j 1.x appender 的功能:

对于简单的 logfile-per-thread appender 你可以使用:

<Routing name="Routing">
  <Routes pattern="$${event:ThreadName}">
    <Route>
      <RollingFile name="Rolling-${event:ThreadName}"
                   fileName="logs/thread-${event:ThreadName}.log"
                   filePattern="logs/thread-${event:ThreadName}.log.%d{yyyy-MM-dd}">
        <PatternLayout pattern="%d [%-5p] [%t] [%c{1}] [%M] - %m%n" />
        <TimeBasedTriggeringPolicy />
      </RollingFile>
    </Route>
  </Routes>
</Routing>

对于更复杂的配置,<Routing> appender 和 <Routes> 都可以包含一个 <Script>(参见 documentation):

  • <Routing> appender 中的脚本可以初始化 staticVariables 地图和 return 默认路由,
  • <Routes> 组件中的脚本根据 staticVariables 和日志记录事件选择适当的路由。