簡體   English   中英

如何以編程方式正確配置 log4j2?

[英]How to properly configure log4j2 programmatically?

我正在嘗試設置 log4j2 以使用RollingFileAppender編寫日志。 我想以編程方式配置日志記錄系統,而不是使用 XML 文件。

這是我嘗試過的(與https://logging.apache.org/log4j/2.x/manual/customconfig.html#Configurator 上的文檔大致相同):

public static void configure(String rootLevel, String packageLevel) {
    ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory
        .newConfigurationBuilder();

    builder.setConfigurationName("RollingBuilder");
    builder.setStatusLevel(Level.TRACE);

    // Create a rolling file appender

    LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
        .addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{1}:%L - %m%n");

    ComponentBuilder triggeringPolicy =
        builder
            .newComponent("Policies")
            .addComponent(
                builder
                    .newComponent("SizeBasedTriggeringPolicy")
                    .addAttribute("size", "200M")
            );

    AppenderComponentBuilder appenderBuilder =
        builder
            .newAppender("rolling", "RollingFile")
            .addAttribute("fileName", "log")
            .addAttribute("filePattern", "log.%d.gz")
            .add(layoutBuilder)
            .addComponent(triggeringPolicy);

    builder.add(appenderBuilder);

    // Create new logger

    LoggerComponentBuilder myPackageLoggerBuilder =
        builder.newLogger("com.mypackage", packageLevel)
            .add(builder.newAppenderRef("rolling"))
            .addAttribute("additivity", false);
    builder.add(myPackageLoggerBuilder);

    RootLoggerComponentBuilder rootLoggerBuilder =
        builder
            .newRootLogger(rootLevel)
            .add(builder.newAppenderRef("rolling"));
    builder.add(rootLoggerBuilder);

    // Initialize logging
    Configurator.initialize(builder.build());
}

我在 main 方法的開頭調用了configure()方法。 當我運行我的程序時會創建一個名為log的文件,但所有日志輸出都轉到標准輸出並且log文件保持為空。

有人可以幫助找出我的配置有什么問題嗎?

我沒有使用任何 log4j 配置文件,如果這有區別的話。 在我的代碼中也使用了 slf4j API。 依賴關系 -

org.apache.logging.log4j:log4j-api:2.11.1
org.apache.logging.log4j:log4j-core:2.11.1
org.apache.logging.log4j:log4j-slf4j-impl:2.11.1
org.slf4j:slf4j-api:1.7.25

首先,此答案是對您評論中提供的其他信息的回應。

我的要求是,當我啟動程序時,我想通過命令行標志控制不同程序包的日志級別

由於您想使用程序參數來控制日志級別,因此建議您看一下Main Arguments LookupRouting Appender 結合使用這兩個功能,您可以設置日志記錄配置,以根據程序參數將日志事件發送到適當的附加程序。

我將提供一個簡單的示例來幫助您。

首先,這里是一個示例Java類,它生成一些日志事件:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.lookup.MainMapLookup;

public class SomeClass {

    private static Logger log = LogManager.getLogger();

    public static void main(String[] args){
        MainMapLookup.setMainArguments(args);

        if(log.isDebugEnabled())
            log.debug("This is some debug!");
        log.info("Here's some info!");
        log.error("Some error happened!");
    }
}

接下來是log4j2的配置文件(有關詳細信息,請參見代碼中的注釋):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
    <Appenders>
        <Routing name="myRoutingAppender">
            <!-- log events are routed to appenders based on the logLevel program argument -->
            <Routes pattern="$${main:logLevel}">
                <!-- If the logLevel argument is followed by DEBUG this route is used -->
                <Route ref="DebugFile" key="DEBUG" />
                <!-- If the logLevel argument is omitted or followed by any other value this route is used -->
                <Route ref="InfoFile" />
            </Routes>
        </Routing>

        <!-- This appender is not necessary, was used to test the config -->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>

        <!-- Below are the 2 appenders used by the Routing Appender from earlier -->
        <File name="DebugFile" fileName="logs/Debug.log" immediateFlush="true"
            append="false">
            <PatternLayout
                pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>

        <File name="InfoFile" fileName="logs/Info.log" immediateFlush="true"
            append="false">
            <PatternLayout
                pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <LevelRangeFilter minLevel="FATAL" maxLevel="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
        </File>
    </Appenders>

    <Loggers>
        <!-- Root logger is set to DEBUG intentionally so that debug events are generated.
             However, events may be ignored by the LevelRangeFilter depending on where they
             are routed by the Routing Appender
         -->
        <Root level="DEBUG">
            <AppenderRef ref="Console" />
            <AppenderRef ref="myRoutingAppender" />
        </Root>
    </Loggers>
</Configuration>

如果不提供“ logLevel”參數,則使用此配置,然后默認情況下會將日志事件路由到“ InfoFile”附加程序,並且通過LevelRangeFilter忽略比INFO更具體的任何事件。

如果提供了“ logLevel”自變量,后跟“ DEBUG”,則日志事件將路由到“ DebugFile”附加程序,並且不會忽略任何事件。

請注意,我確實嘗試使用查找來設置日志級別,但是似乎無法通過查找來配置日志級別參數。 這就是為什么我不得不使用這種替代方法。 我對這種方法的擔心是,正如我在配置文件中的注釋中指出的那樣,日志級別必須保持在DEBUG,這意味着即使不使用DEBUG事件,您也始終會生成DEBUG事件。 這可能會影響性能。 一種解決方法是使用程序參數來確定是否需要生成調試事件。 例如:

通常,您將使用:

if(log.isDebugEnabled())
    log.debug("This is some debug!");

但是當使用上述配置時,您將使用類似以下內容:

if("DEBUG".equals(args[1]))
    log.debug("This is some debug!");

如果需要,可以使用枚舉(甚至可以使用log4j2提供的Level類)來提高效率。

我希望這可以幫助您入門。

請找到示例Root日志,最后需要調用重新配置函數。

RootLoggerComponentBuilder rootLogger = builder
   .newRootLogger(Level.ALL)
   .add(builder.newAppenderRef("LogToRollingFile"));

LoggerComponentBuilder logger = builder
   .newLogger("MyClass",Level.ALL)
   .addAttribute("additivity", false);

Configurator.reconfigure(builder.build());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM