Làm cách nào để thêm phần phụ Log4J2 vào thời gian chạy theo chương trình? (How to add Log4J2 appenders at runtime programmatically?)


問題描述

Làm cách nào để thêm phần phụ Log4J2 vào thời gian chạy theo chương trình? (How to add Log4J2 appenders at runtime programmatically?)

Is it possible to add Log4J2 appenders programmatically using the specifications from the XML configuration?

I plan to define it all in the log4j2.xml and then pick appenders situationally like this (won't compile):

if (arg[0].equals("log") ) {
    Logger.getLogger("loggerNameFromXMLConfig").addAppender("appenderNameFromXMLConfig");
} else {
    //...
}

參考解法

方法 1:

There have been a number of requests to support better programmatic configuration for Log4j 2. Sorry it took so long. As of Log4j 2.4, API was added to log4j‑core to facilitate programmatic configuration.

The new ConfigurationBuilder API allows users to construct component definitions. With this API, there is no need to work directly with actual configuration objects (like LoggerConfig and FileAppender) which require a lot of knowledge on how Log4j works under the hood. Component definitions are added to the ConfigurationBuilder, and once all the definitions have been collected all the actual configuration objects (like Loggers and Appenders) are constructed. It feels a bit like the XML configuration syntax, except that you are writing Java code.

Note that the new ConfigurationBuilder API allows user code to create a new configuration or completely replace the existing configuration. If your use case is different, and you want to programmatically modify (rather than replace) an existing configuration after Log4j was started, then you will need to work with actual configuration objects. In that case, please see the Programmatically Modifying the Current Configuration after Initialization section of the manual.

方法 2:

Edit: for the newest versions of log4j2, see https://stackoverflow.com/a/33472893/1899566 instead.

I get the impression they don't want you doing this, but this works for me:

<pre class="lang‑java prettyprint‑override">if (arg[0].equals("log") ) {
  org.apache.logging.log4j.Logger logger
    = org.apache.logging.log4j.LogManager.getLogger("loggerNameFromXMLConfig");
  org.apache.logging.log4j.core.Logger coreLogger
    = (org.apache.logging.log4j.core.Logger)logger;
  org.apache.logging.log4j.core.LoggerContext context
    = (org.apache.logging.log4j.core.LoggerContext)coreLogger.getContext();
  org.apache.logging.log4j.core.config.BaseConfiguration configuration
    = (org.apache.logging.log4j.core.config.BaseConfiguration)context.getConfiguration();

  coreLogger.addAppender(configuration.getAppender("appenderNameFromXMLConfig"));
} else {
  //...
}
</code></pre>

方法 3:

As I noted above, I couldn't get https://logging.apache.org/log4j/2.x/manual/customconfig.html#AddingToCurrent to work, at least, not the way I expected it to (my appender would never get messages routed to it).  I did finally stumble across a pattern that works for me ‑ allowing me to add an appender at runtime, and have that appender actually get log messages routed to it.

Edit I removed a bunch of confusing code from here that wasn't doing anything....

    LoggerContext lc = (LoggerContext) LogManager.getContext(false);
    FileAppender fa = FileAppender.newBuilder().withName("mylogger").withAppend(false).withFileName(new File(outputDirectory, "ConsoleOutput.txt").toString())
            .withLayout(PatternLayout.newBuilder().withPattern("%‑5p %d  [%t] %C{2} (%F:%L) ‑ %m%n").build())
            .setConfiguration(lc.getConfiguration()).build();
    fa.start();
    lc.getConfiguration().addAppender(fa);
    lc.getRootLogger().addAppender(lc.getConfiguration().getAppender(fa.getName()));
    lc.updateLoggers();

A key point for me, was that calling addAppender and passing your appender directly doesn't work, but asking for your appender back by name seems to.  Which doesn't make sense... but since working, and I'm tired of wasting time on something that should be so simple....

方法 4:

In Log4j2 structure

        ‑‑‑"Config"‑‑‑
                Appenders
                        Appender(0)
                            Console
                        Appender(1)
                            File
                    LoggerConfigs
                        ‑‑ LoggerConfig(0) 
                        ‑‑ LoggerConfig(1)
                        ‑‑ LoggerConfig(2)

        ‑‑‑‑"LoggerConfig"‑‑‑‑
                ‑ AppenderRefs
                    ‑‑ AppenderRef(0)
                        ‑‑ Name Console
                        ‑‑ Level : DEBUG
                ‑ Appenders
                    ‑‑ Appender(0)
                        ‑‑ Name Console
                        ‑‑ Level : DEBUG
                ‑ Level ‑‑ ALL

loggerConfig.getAppenders() ‑‑> Will return the Appenders in "Config". For me this is a BUG

loggerConfig.getAppenderRefs() ‑‑> is working well !!

方法 5:

I don't know if it's useful: An Appender can be added to a Logger by calling the addLoggerAppender method of the current Configuration.  reference:http://logging.apache.org/log4j/2.x/manual/architecture.html

(by Brian JohnsonRemko PopmaRobert Fleminguser2163960Christian KlugesherzXiaoyuan)

參考文件

  1. How to add Log4J2 appenders at runtime programmatically? (CC BY‑SA 3.0/4.0)

#log4j2 #java #logging #log4j






相關問題

Làm cách nào để thêm phần phụ Log4J2 vào thời gian chạy theo chương trình? (How to add Log4J2 appenders at runtime programmatically?)

使用 Spring 和 Log4j2 的 Classloader-Leak (Classloader-Leak with Spring and Log4j2)

log4j2 RolllingFileAppender filePattern 創建日期錯誤 (log4j2 RolllingFileAppender filePattern create a wrong date)

將時間戳添加到日誌文件名時出錯 (log4j2) (Error adding timestamp to log file name (log4j2))

log4j2 - 以編程方式更改 RollingFileAppender 的最大文件大小 (log4j2 - programmatically change max file size of RollingFileAppender)

log4j 沒有登錄到文件或控制台 (log4j is not logging into file or console)

Log4j2 未在 Linux 中使用 Spring Boot 創建日誌文件 (Log4j2 not creating log file with Spring Boot in Linux)

application.properties 中的外部 log4j2.xml 文件路徑 (External log4j2.xml file path in application.properties)

使用 Spring 的依賴於配置文件的 log4j2 配置 (Profile-dependent log4j2 configuration with Spring)

從 log4j2.xml 訪問環境變量 (Accessing environment variable from log4j2.xml)

Spring Boot 應用程序中的內部 tomcat 停止響應調用 (internal tomcat inside spring boot application stops responding to calls)

如何在 mule 應用程序中實現 log4j2 (2.14.0) 'JSON 模板佈局'? (How can I implement log4j2 (2.14.0) 'JSON Template Layout' in a mule application?)







留言討論