我使用以下 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}当我可以在应用程序中使用系统参数时,如何避免被创建?
只需将 ${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”以使其正确匹配)。如果您的目标是在启动时简单地通过参数设置日志文件,则不需要代码。
| 归档时间: |
|
| 查看次数: |
10945 次 |
| 最近记录: |