将Log4j2系统属性写为文件

时间:2015-12-03 15:45:15

标签: 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>

当文件位置作为命令行参数传递时设置系统参数,然后函数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();
    }

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

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

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

private final static Logger logger = LogManager.getLogger(Connector.class);

问题是当我运行应用程序时,正在创建${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}

可以看出系统参数是字面上的选择而不是替换。我需要避免早期初始化并仅在调用reconfigureLog方法后启动此加载。 当我可以将系统参数用作应用程序的一部分时,如何避免创建${sys.log.file}

1 个答案:

答案 0 :(得分:2)

TL; DR

只需使用$ {main: - value}查找替换$ {sys: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>

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