如何在运行时为每个类重新初始化logger log4j

vatpfxk5  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(153)

我以前从未使用过日志,我想在应用程序中间再次初始化每个类的日志。我们使用log4j,在each类上,我们有

public class MyClass {

    private static Logger logger = Logger.getLogger(MyClass.class);

    public void method(){
        logger.info("This is info");
    }

因此,我想要在应用程序运行时的某个时间点重新初始化这个logger对象。

private static Logger logger = Logger.getLogger(MyClass.class);

当我的应用程序正在运行并且用户执行某个操作时,

目的:

我的真实的目标是将这些日志文件存储在磁盘上。但我希望根据用户操作将日志文件存储在不同的文件夹中。因此,我们的应用程序中有两个siteIDs,因此,我们在磁盘上创建了两个文件夹,我们希望在其中存储日志文件。因此,当站点被选中时,这些each class上的logger对象需要重新初始化。有什么建议吗?下面是我的log.properties文件:

logger.pattern=%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n
logger.base.dir=../logs
logger.archive.dir=/archive
logger.archived.file.pattern=_%d{dd-MM-yyyy}.%i
logger.file.ext=.log
logger.file.size=10 mb
logger.archived.size.cap=100 mb
logger.file.retention.days=7
logger.debug.file.retention.days=1
logger.level=TRACE

然后我们有一个名为LoggerConfig的类

public class LoggerConfig {

private static LoggerConfig loggerConfig = null;

private Properties prop = new Properties();

private String pattern;
private String baseDir;
private String archiveDir;
private String archivedFilePattern;
private String fileExt;
private String fileSize;
private String archivedSizeCap;
private Integer fileRetentionDays;
private Integer debugFileRetentionDays;
private Level loggerLevel;

private LoggerConfig() {

    loadProperties();
}

public static LoggerConfig getInstance() {
    if (loggerConfig == null) {
        loggerConfig = new LoggerConfig();
    }
    return loggerConfig;
}

private void loadProperties() {
    try {
        InputStream input = LoggerConfig.class.getClassLoader().getResourceAsStream("logger.properties");
        prop.load(input);
        this.pattern = prop.getProperty("logger.pattern");
        this.baseDir = prop.getProperty("logger.base.dir");
        this.archiveDir = prop.getProperty("logger.archive.dir");
        this.archivedFilePattern = prop.getProperty("logger.archived.file.pattern");
        this.fileExt = prop.getProperty("logger.file.ext");
        this.fileSize = prop.getProperty("logger.file.size");
        this.archivedSizeCap = prop.getProperty("logger.archived.size.cap");
        this.fileRetentionDays = Integer.parseInt(prop.getProperty("logger.file.retention.days"));
        this.debugFileRetentionDays = Integer.parseInt(prop.getProperty("logger.debug.file.retention.days"));
        this.loggerLevel = Level.toLevel(prop.getProperty("logger.level"));
    } catch (Exception ex) {
        System.out.println("Exception occourred while loading the configration file " + ex);
    }
}

/**
 * Getters and setters
 */

最后是另一个Logger文件:

public class ApplicationLogger {

    private static LoggerConfig config = LoggerConfig.getInstance();

    private static Map<String, Logger> loggers = new HashMap<String, Logger>();

    public static Logger getLogger(String orgID, Class<?> className) {
        init(orgID, className);
        return loggers.get(orgID);
    }

    private static void init(String orgID, Class<?> className) {
        if (!loggers.containsKey(orgID)) {
            LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
            Logger logger = loggerContext.getLogger(orgID + className);
            logger.setAdditive(Boolean.FALSE);
            logger.setLevel(config.getLoggerLevel());

            logger.addAppender(getFileAppender(loggerContext, Level.TRACE, orgID));
            logger.addAppender(getFileAppender(loggerContext, Level.DEBUG, orgID));
            logger.addAppender(getFileAppender(loggerContext, Level.INFO, orgID));
            logger.addAppender(getFileAppender(loggerContext, Level.WARN, orgID));
            logger.addAppender(getFileAppender(loggerContext, Level.ERROR, orgID));

            loggers.put(orgID, logger);
        }
    }

    private static FileAppender<ILoggingEvent> getFileAppender(LoggerContext loggerContext, Level level, String orgID) {

        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(loggerContext);
        encoder.setPattern(config.getPattern());
        encoder.setImmediateFlush(Boolean.TRUE);
        encoder.start();

        LevelFilter filter = new LevelFilter();
        filter.setContext(loggerContext);
        filter.setLevel(level);
        filter.setOnMismatch(FilterReply.DENY);
        filter.start();

        RollingFileAppender<ILoggingEvent> fileAppender = new RollingFileAppender<ILoggingEvent>();

        SizeAndTimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new SizeAndTimeBasedRollingPolicy<ILoggingEvent>();
        rollingPolicy.setContext(loggerContext);
        rollingPolicy.setFileNamePattern(config.getBaseDir() + config.getArchiveDir() + File.separator + orgID
                + File.separator + level.toString() + config.getArchivedFilePattern() + config.getFileExt());
        rollingPolicy.setMaxFileSize(FileSize.valueOf(config.getFileSize()));
        rollingPolicy.setMaxHistory(
                Level.DEBUG.equals(level) ? config.getDebugFileRetentionDays() : config.getFileRetentionDays());
        rollingPolicy.setTotalSizeCap(FileSize.valueOf(config.getArchivedSizeCap()));
        rollingPolicy.setParent(fileAppender);
        rollingPolicy.start();
        fileAppender.setContext(loggerContext);
        fileAppender.setAppend(true);
        fileAppender.setEncoder(encoder);
        fileAppender.addFilter(filter);
        fileAppender.setFile(
                config.getBaseDir() + File.separator + orgID + File.separator + level.toString() + config.getFileExt());
        fileAppender.setRollingPolicy(rollingPolicy);
        fileAppender.start();

        return fileAppender;
    }

}

请注意,orgID是由用户更改的站点ID,更改后,我希望重新初始化所有logger对象

2o7dmzc5

2o7dmzc51#

在Log4j2中,一个标准的解决方案是使用一个日志记录器,即ThreadContextRoutingAppender。这几乎不需要编程配置:
1.在开始处理请求时,您需要为siteIdThreadContext键填写一个值:

ThreadContext.put("siteId", "site1");

1.在您的log4j2.xml文件中,您需要配置一个路由追加器,它根据siteId的值选择真实的的追加器:

<Configuration>
  <Appenders>
    <RollingFile name="ROLLING-site1" fileName="..." filePattern="...">
      ...
    </RollingFile>
    <RollingFile name="ROLLING-site2" fileName="..." filePattern="...">
      ...
    </RollingFile>
    <Routing name="ROUTING">
      <Routes pattern="$${ctx:siteId}">
        <Route key="site1" appenderRef="ROLLING-site1" />
        <Route key="site2" appenderRef="ROLLING-site2" />
      </Routes>
    </Routing>
  </Appenders>
  <Loggers>
    <Root level="DEBUG">
      <AppenderRef ref="ROUTING" />
    </Root>
  </Loggers>
</Configuration>

1.您的类可以使用从LogManager.getLogger获得的静态记录器,并且不需要知道选择追加器背后的逻辑。
类似的配置可能可以在Logback中使用过滤器获得,但我对Logback的了解非常有限。

相关问题