Log4j2 系统属性写入文件

dma*_*hop 5 java log4j2

我使用以下 log4j2 配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5.5level %-60.60logger - %msg%n" />
            <Filters>
                <ThresholdFilter level="info" onMatch="ACCEPT"
                    onMismatch="DENY" />
            </Filters>
        </Console>
        <RollingFile name="RollingFile"
            fileName="${sys:log.file}"
            filePattern="${sys:log.parent.path}\$${date:yyyy-MM}\${sys:log.file.name}-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout>
                <Pattern>
                    %d{yyy-MM-dd HH:mm:ss.SSS} [%30.30t]%-10.10level%-60.60logger - %msg%n
                </Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="60 MB" />
            </Policies>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="RollingFile" />
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>
Run Code Online (Sandbox Code Playgroud)

当文件位置作为命令行参数传递时,系统参数被设置,然后函数 reconfigureLog() 设置属性

public static void reconfigureLog(String logPath)
    {
        File logFile = new File(logPath);
        System.setProperty("log.file", logPath);
        System.setProperty("log.parent.path", logFile.getParent());
        System.setProperty("log.file.name", FilenameUtils.getBaseName(logFile.getName()));

        org.apache.logging.log4j.core.Logger rootLogger = (org.apache.logging.log4j.core.Logger) LogManager
                .getRootLogger();
        LoggerContext context = rootLogger.getContext();
        context.reconfigure();
    }
Run Code Online (Sandbox Code Playgroud)

这是我从命令行读取参数然后再设置的场景的示例用法。

if (cmd.hasOption("logFile"))
        {
            String logPath = cmd.getOptionValue("logFile");
            Utility.reconfigureLog(logPath);
            logger = LogManager.getLogger(Test.class);
        }
Run Code Online (Sandbox Code Playgroud)

每个类都有一个静态记录器初始化,如下所示:

private final static Logger logger = LogManager.getLogger(Connector.class);
Run Code Online (Sandbox Code Playgroud)

问题是当我运行应用程序时,${sys.log.file}正在创建应用程序,然后根据参数创建相应的日志文件。通过参数摸索,似乎是自动添加了RolllingFile下的参数fileName。

log4j2的调试日志是:

2015-12-03 11:07:19,204 main DEBUG Calling createAppender on class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile with params(fileName="${sys:log.file}", filePattern="${sys:log.parent.path}\${date:yyyy-MM}\${sys:log.file.name}-%d{MM-dd-yyyy}-%i.log.gz", append="null", name="RollingFile", bufferedIO="null", bufferSize="null", immediateFlush="null", Policies(CompositeTriggeringPolicy(policies=[TimeBasedTriggeringPolicy(nextRolloverMillis=0, interval=1, modulate=false), SizeBasedTriggeringPolicy(size=62914560)])), null, PatternLayout(%d{yyy-MM-dd HH:mm:ss.SSS} [%30.30t]%-10.10level%-60.60logger - %msg%n), null, ignoreExceptions="null", advertise="null", advertiseURI="null", Configuration(<path>\Connector\target\classes\log4j2.xml))
2015-12-03 11:07:19,207 main DEBUG Starting RollingFileManager ${sys:log.file}
Run Code Online (Sandbox Code Playgroud)

可以看出,系统参数是按字面意思选取的,而不是替换的。我需要避免早期初始化并仅在调用 reconfigureLog 方法后才开始加载。${sys.log.file}当我可以在应用程序中使用系统参数时,如何避免被创建?

ala*_*678 7

长话短说

只需将 ${sys:value} 查找替换为 ${main:--value} 查找即可。

解释

http://logging.apache.org/log4j/2.x/manual/lookups.html#AppMainArgsLookup

将此功能与配置属性结合起来

http://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution

您可以使用参数进行一些非常强大的配置,而无需接触代码。

请密切关注 PropertySubstitution 文档中的这一点。

如果在查找中找不到与前缀关联的键的值,则将使用与配置文件中属性声明中的键关联的值。如果未找到值,则变量声明将作为值返回。可以通过执行以下操作在配置中声明默认值:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Properties>
    <Property name="--file">log_file_path</property>
  </Properties>
  ...
</Configuration>
Run Code Online (Sandbox Code Playgroud)

这意味着像这样的配置查找${main:--file}将返回命令行参数 --file 如果存在,但如果不存在,则会返回属性声明中的默认值(我不确定属性的名称是否需要为“file”)或“--file”以使其正确匹配)。如果您的目标是在启动时简单地通过参数设置日志文件,则不需要代码。