log4j2-appender可以“同时”管理多个文件吗?

2ul0zpep  于 2021-07-07  发布在  Java
关注(0)|答案(0)|浏览(220)

我想创建一个appender,使用mdc/threadcontext将每个用户的操作记录到不同的文件中,以保存用户名,并在以后使用它命名文件。
所以对于user1,我们有“web\u debug\u user1\u yyyy-mm-dd”,对于user2,我们有“web\u debug\u user2\u 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 &lt;%X{userId}&gt;&lt;%X{customerID}&gt;&lt;%X{oid}&gt; [%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仍然指向同一个outputstream,那么更改filemanager的文件名似乎还不够,这样就可以将所有不同的用户消息记录到属于应用程序中第一个登录用户的文件中。经过一些调试,发现outputstream只在两种情况下发生更改:filemanager初始化和rollover。然后,当当前用户发生更改时,强制在自定义策略中进行滚动,但每次滚动后都会创建一个新文件,而不会写入以前存在的文件,因此在10分钟的时间内,有20-30个不同的文件。
所以问题是:有没有办法让appender使用以前的文件,比如说“回滚”,而不仅仅创建一个新文件?
我的方法错了吗?
谢谢。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题