服务器重启或更改 xml 配置文件后如何保留 log4j2 的插件配置
How to retain log4j2's plugin configs after server restart or altering xml config file
我开发了一个自定义滚动文件附加程序,它工作正常。唯一的问题是每次我重新启动服务器或更改 log4j2.xml 文件(文件的任何部分)时它都会重新初始化,突然间所有以前的日志都会被擦除。我没有在随附的默认附加程序中观察到这种行为,所以我想知道如何才能保留我的配置。
<CustomAppender name="CustomAppender"
fileName="${log.file.directory}/file.log"
filePattern="${log.file.directory}/file.log.%d{yyyy-MM-dd}-%i.gz"
immediateflush="true"
append="true">
<CustomLayout/>
<Policies>
<SizeBasedTriggeringPolicy size="3 KB"/>
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
</CustomAppender>
P.S。我试图让它成为一个单例,但除此之外它没有用我真的不想让它远离被重新配置,我只想保留我以前生成的日志。
更新
显然,每次服务器关闭或 log4j2.xml 文件被更改时,管理器都会从头开始重建附加程序,尽管内置附加程序即使在重新启动或重新配置后也会保持其状态。他们通过覆盖 AbstractOutputStreamAppender 中的“stop”方法来做到这一点。我对我的 appender 做了同样的事情,但它仍然没有像我预期的那样表现。
@Override
public boolean stop(long timeout, TimeUnit timeUnit) {
setStopping();
final boolean stopped = super.stop(timeout, timeUnit, false);
setStopped();
return stopped;
}
这是我在 appender builder 中使用的管理器:
final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, append,
isBufferedIo, policy, strategy, advertiseUri, layout, bufferSize, isImmediateFlush(),
createOnDemand, filePermissions, fileOwner, fileGroup, getConfiguration());
if (manager == null) {
return null;
}
manager.initialize();
重新配置时会发生以下情况:
- 新的配置文件被读取并转换为节点树。
- 访问与节点关联的插件并创建其对应的类。
- 如果配置创建成功,它就会启动。
- 记录器已更新以引用新配置。
- 旧配置已停止。
如您所想,由于同时有两个配置 运行 这可能会导致问题。例如,如果两个组件都尝试使用同一个端口,那么第二个配置可能会失败。为了避免这些问题,Log4j 2 中的 Appenders 使用了 Managers。管理器通常会有一个“名称”,其中包括任何项目,如果它们在新配置中具有相同的值,则表明应该重用管理器。这允许像 OutputStreams 这样的东西在重新配置期间保持打开状态。但是,这样做的副作用是,如果参数在 appender 上更改并且不是“名称”的一部分,那么值的更改可能会被忽略,因为管理器未被修改。
因此,在创建新的Appender 时,必须注意传递给Manager 的名称,并且Appender 应尝试更新Manager 中不属于名称的相关值。此外,Manager 必须考虑到它被多次启动和停止。 AbstractManager 实际上会为您处理这个。
我开发了一个自定义滚动文件附加程序,它工作正常。唯一的问题是每次我重新启动服务器或更改 log4j2.xml 文件(文件的任何部分)时它都会重新初始化,突然间所有以前的日志都会被擦除。我没有在随附的默认附加程序中观察到这种行为,所以我想知道如何才能保留我的配置。
<CustomAppender name="CustomAppender"
fileName="${log.file.directory}/file.log"
filePattern="${log.file.directory}/file.log.%d{yyyy-MM-dd}-%i.gz"
immediateflush="true"
append="true">
<CustomLayout/>
<Policies>
<SizeBasedTriggeringPolicy size="3 KB"/>
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
</CustomAppender>
P.S。我试图让它成为一个单例,但除此之外它没有用我真的不想让它远离被重新配置,我只想保留我以前生成的日志。
更新
显然,每次服务器关闭或 log4j2.xml 文件被更改时,管理器都会从头开始重建附加程序,尽管内置附加程序即使在重新启动或重新配置后也会保持其状态。他们通过覆盖 AbstractOutputStreamAppender 中的“stop”方法来做到这一点。我对我的 appender 做了同样的事情,但它仍然没有像我预期的那样表现。
@Override
public boolean stop(long timeout, TimeUnit timeUnit) {
setStopping();
final boolean stopped = super.stop(timeout, timeUnit, false);
setStopped();
return stopped;
}
这是我在 appender builder 中使用的管理器:
final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, append,
isBufferedIo, policy, strategy, advertiseUri, layout, bufferSize, isImmediateFlush(),
createOnDemand, filePermissions, fileOwner, fileGroup, getConfiguration());
if (manager == null) {
return null;
}
manager.initialize();
重新配置时会发生以下情况:
- 新的配置文件被读取并转换为节点树。
- 访问与节点关联的插件并创建其对应的类。
- 如果配置创建成功,它就会启动。
- 记录器已更新以引用新配置。
- 旧配置已停止。
如您所想,由于同时有两个配置 运行 这可能会导致问题。例如,如果两个组件都尝试使用同一个端口,那么第二个配置可能会失败。为了避免这些问题,Log4j 2 中的 Appenders 使用了 Managers。管理器通常会有一个“名称”,其中包括任何项目,如果它们在新配置中具有相同的值,则表明应该重用管理器。这允许像 OutputStreams 这样的东西在重新配置期间保持打开状态。但是,这样做的副作用是,如果参数在 appender 上更改并且不是“名称”的一部分,那么值的更改可能会被忽略,因为管理器未被修改。
因此,在创建新的Appender 时,必须注意传递给Manager 的名称,并且Appender 应尝试更新Manager 中不属于名称的相关值。此外,Manager 必须考虑到它被多次启动和停止。 AbstractManager 实际上会为您处理这个。