示例依赖log4j2.xml,需要预先在里面创建一个配置模版


log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN" shutdownHook="disable">
    <Properties>
        <Property name="sysName">schedule</Property>
        <Property name="bizLogLevel">@[email protected]</Property>
        <Property name="otherLogLevel">@[email protected]</Property>
        <Property name="logFilePath">@[email protected]</Property>
        <Property name="logSize">@[email protected]</Property>
        <Property name="maxFile">100</Property>
        <Property name="errorLogFile">${sysName}_err</Property>
        <Property name="allLogFile">${sysName}_all</Property>
    </Properties>
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout charset="UTF-8" pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%t] [%c:%line] - %msg%n"/>
        </Console>
        <RollingFile name="TaskCfgRollingFile" fileName="${logFilePath}/task-log-factory.log"
                     filePattern="${logFilePath}/$${date:yyyy-MM}/${errorLogFile}-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout charset="UTF-8" pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%t] [%c:%line] - %msg%n"/>
            <Filters>
                <ThresholdFilter level="${bizLogLevel}"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${logSize}"/>
            </Policies>
        </RollingFile>
        <RollingFile name="AllRollingFile" fileName="${logFilePath}/${allLogFile}.log"
                     filePattern="${logFilePath}/$${date:yyyy-MM}/${allLogFile}-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout charset="UTF-8" pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%t] [%c:%line] - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${logSize}"/>
            </Policies>
        </RollingFile>
    </appenders>
    <loggers>
        <logger name="TaskCfgLogger" level="${bizLogLevel}" additivity="false">
            <appender-ref ref="TaskCfgRollingFile"/>
            <appender-ref ref="Console"/>
        </logger>
        <root level="${otherLogLevel}">
            <appender-ref ref="AllRollingFile"/>
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>

package org.ideap.schedule.log;

/**
 * Created by xiongpu on 2017/7/3.
 */
public class AbyLogConfig {
    /**
     * log4j2.xml 里面定义的logger name 用来作为配置模板,目前支持 RollingFileAppender,ConsoleAppender,FileAppender
     */
    private String cfgLogName;
    /**
     * 定义的logger 名称
     */
    private String name;
    /**
     * fileName="${logFilePath}/task-log-factory.log" 要替换的内容 比如这里task-log-factory替换为任务名称
     */
    private String fileNameKey;
    /**
     * 替换值 如任务名
     */
    private String fileName;

    // 省略get set
}

package org.ideap.schedule.log;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
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.appender.RollingFileAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by xiongpu on 2017/7/3.
 */
public class AbyLogFactory {
    private static AbyLogFactory abyLogFactory = new AbyLogFactory();

    private AbyLogFactory() {
    }

    public static AbyLogFactory getAbyLogFactory() {
        return abyLogFactory;
    }


    public void start(AbyLogConfig abyLogConfig) {
        //false时,返回多个LoggerContext对象, true:返回唯一的单例LoggerContext
        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        final Configuration config = ctx.getConfiguration();
        org.apache.logging.log4j.core.Logger cfgLogger = (org.apache.logging.log4j.core.Logger) LogManager.getLogger(abyLogConfig.getCfgLogName());
        if (cfgLogger == null) {
            LogManager.getLogger(AbyLogFactory.class).error("not found {} logger (please define in log4j2.xml)", abyLogConfig.getCfgLogName());
            return;
        }
        Map<String, Appender> appenderMap = cfgLogger.getAppenders();
        List<AppenderRef> appenderRefs = new ArrayList<>();
        List<Appender> appenders = new ArrayList<>();
        appenderMap.forEach((key, appenderCfg) -> {
            Appender appender = getAppender(abyLogConfig, config, appenderCfg);
            if (appender != null) {
                appender.start();
                config.addAppender(appender);
                AppenderRef ref = AppenderRef.createAppenderRef(appender.getName(), null, null);
                appenderRefs.add(ref);
                appenders.add(appender);
            }
        });
        if (CollectionUtils.isEmpty(appenders)) return;
        AppenderRef[] refs = new AppenderRef[appenderRefs.size()];
        refs = appenderRefs.toArray(refs);
        LoggerConfig loggerConfig = LoggerConfig.createLogger(false, Level.ALL, abyLogConfig.getName(),
                "true", refs, null, config, null);
        appenders.stream().forEach(e ->
                loggerConfig.addAppender(e, Level.ALL, null)
        );
        config.addLogger(abyLogConfig.getName(), loggerConfig);
        ctx.updateLoggers(config);
    }


    private Appender getAppender(AbyLogConfig abyLogConfig, Configuration config, Appender appenderCfg) {
        Appender appender = null;
        if (appenderCfg instanceof RollingFileAppender) {
            RollingFileAppender rollingFileAppender = (RollingFileAppender) appenderCfg;
            appender = RollingFileAppender.newBuilder()
                    .withConfiguration(config)
                    .withName(abyLogConfig.getName() + "RollingFile")
                    .withFileName(rollingFileAppender.getFileName().replaceAll(abyLogConfig.getFileNameKey(), abyLogConfig.getFileName()))
                    .withFilePattern(rollingFileAppender.getFilePattern())
                    .withLayout(rollingFileAppender.getLayout())
                    .withFilter(rollingFileAppender.getFilter())
                    .withPolicy(rollingFileAppender.getTriggeringPolicy())
                    .build();
        } else if (appenderCfg instanceof ConsoleAppender) {
            ConsoleAppender consoleAppender = (ConsoleAppender) appenderCfg;
            appender = ConsoleAppender.newBuilder()
                    .withName(abyLogConfig.getName() + "Console")
                    .withLayout(consoleAppender.getLayout())
                    .build();
        } else if (appenderCfg instanceof FileAppender) {
            FileAppender fileAppender = (FileAppender) appenderCfg;
            appender = FileAppender.newBuilder()
                    .withConfiguration(config)
                    .withName(abyLogConfig.getName() + "File")
                    .withFileName(fileAppender.getFileName().replaceAll(abyLogConfig.getFileNameKey(), abyLogConfig.getFileName()))
                    .withLayout(fileAppender.getLayout())
                    .withFilter(fileAppender.getFilter())
                    .build();
        } else {
            LogManager.getLogger(AbyLogFactory.class).warn("unsupported appender type ,appender type not in(RollingFileAppender,ConsoleAppender,FileAppender)", appenderCfg.getClass());
        }
        return appender;
    }


    /**
     * 获取Logger
     *
     * @param abyLogConfig
     * @return
     */
    public Logger createLogger(AbyLogConfig abyLogConfig) {
        if (!LogManager.exists(abyLogConfig.getName())) {
            start(abyLogConfig);
        }
        return LogManager.getLogger(abyLogConfig.getName());
    }

}

测试


package org.ideap.schedule;

import org.apache.logging.log4j.Logger;
import org.ideap.schedule.log.AbyLogConfig;
import org.ideap.schedule.log.AbyLogFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class AbyScheduleServerApplicationTests {

   @Test
   public void contextLoads() {
      AbyLogConfig abyLogConfig=new AbyLogConfig();
      abyLogConfig.setName("test1");
      abyLogConfig.setCfgLogName("TaskCfgLogger");
      abyLogConfig.setFileNameKey("task-log-factory");
      abyLogConfig.setFileName(abyLogConfig.getName());
      Logger logger= AbyLogFactory.getAbyLogFactory().createLogger(abyLogConfig);
      logger.info("------------创建成功--------------");
      logger.error("------------创建成功--------------");

   }

}

测试结果

动态创建Logger


参考:https://www.feehi.com/view/4346


有问题欢迎指正~


相关文章: