我想创建一个附加程序,使用 MDC / ThreadContext 将每个用户操作记录到每个用户的不同文件中,以保存用户名并在以后使用它来命名文件。
因此,对于 User1,我们将拥有“web_debug_user1_yyyy-MM-DD”,对于 user2,我们将拥有“web_debug_user2_yyyy-MM-DD”。
这些用户可以同时登录应用程序。
这是配置的相关部分:
<Properties>
<Property name="logPath">/data/logs</Property>
<Property name="rollingFileName">web_debug</Property>
<Property name="rollingFileNameError">web_Error</Property>
<Property name="patternLog">%d %-5p [%c] %m [SID: %X{sessionId}]%n</Property>
<Property name="patternLogUser">%d %-5p <%X{userId}><%X{customerID}><%X{oid}> [%c] %m [SID: %X{sessionId}]%n</Property>
</Properties>
<Appenders>
<RollingFile name="rollingFileUser"
filePattern="${logPath}/${rollingFileName}_$${ctx:userId}%d{yyyy-MM-dd}_%i.txt">
<PatternLayout pattern="${patternLogUser}" />
<Policies>
<UserLoggingTriggerPolicy />
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
<DirectWriteRolloverStrategy />
</RollingFile>
这是自定义策略 UserLoggingTriggeringPolicy,每次启动用户事件时都会在管理器上设置 fileName 属性。
@Plugin(name = "UserLoggingTriggerPolicy", category = "Core")
public class UserLoggingTriggerPolicy implements TriggeringPolicy {
private RollingFileManager manager;
private String typelog;
private File[] debugFilesUser;
@Override
public void initialize(RollingFileManager manager) {
this.manager = manager;
this.typelog = manager.getFileName().contains("debug") ? "debug" : "Error";
this.debugFilesUser = null;
}
@Override
public boolean isTriggeringEvent(LogEvent arg0) {
return isRolling();
}
public boolean isRolling() {
boolean roll = false;
if (!this.manager.getFileName().contains(MDC.get("userId"))) {
((DirectFileRolloverStrategy) manager.getRolloverStrategy()).clearCurrentFileName();
((DirectFileRolloverStrategy) manager.getRolloverStrategy()).getCurrentFileName(manager);
}
File f = new File(this.manager.getFileName());
File folder = new File(f.getParent());
if (debugFilesUser == null) {
getFiles(folder);
}
if ((debugFilesUser.length != 0 && debugFilesUser[debugFilesUser.length - 1].length() / 1024 / 1024 > 10)
|| !f.exists()) {
debugFilesUser = null;
roll = true;
}
return roll;
}
private void getFiles(File folder) {
debugFilesUser = folder.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if (name.contains(MDC.get("userId")) && name.contains(typelog)) {
return true;
}
return false;
}
});
}
@PluginFactory
public static UserLoggingTriggerPolicy createPolicy() {
return new UserLoggingTriggerPolicy();
}
}
问题是,更改 FileManager 的 FileName 似乎还不够,因为它仍然指向相同的 OutputStream,因此将所有不同的用户消息记录到属于应用程序中第一个登录用户的文件中。经过一些调试发现OutputStream只在两种情况下发生变化:FileManager的初始化和RollOver。然后在当前用户更改时强制在自定义策略中进行翻转,但最终在每次滚动后创建一个新文件,而不是写入以前存在的文件,因此在 10 分钟内有 20-30 个不同的文件。
所以问题是(是):有没有办法让附加程序使用以前的文件,比如说“回滚”,而不仅仅是创建一个新文件?
我的方法错了吗?
谢谢。