#java #logging #log4j2 #mdc #threadcontext
#java #ведение журнала #log4j2 #mdc #threadcontext
Вопрос:
Я хочу создать приложение, которое регистрирует каждое действие пользователя в отдельный файл для каждого пользователя, используя MDC / ThreadContext для сохранения имени пользователя и последующего использования его для присвоения имени файлу.
Таким образом, для пользователя 1 у нас будет «web_debug_user1_yyyy-MM-DD», для пользователя 2 «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 amp;<%X{userId}amp;>amp;<%X{customerID}amp;>amp;<%X{oid}amp;> [%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 amp;amp; 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")) amp;amp; name.contains(typelog)) {
return true;
}
return false;
}
});
}
@PluginFactory
public static UserLoggingTriggerPolicy createPolicy() {
return new UserLoggingTriggerPolicy();
}
}
Дело в том, что кажется недостаточным изменить имя файла FileManager, учитывая, что он по-прежнему указывает на один и тот же выходной поток, таким образом регистрируя все разные сообщения пользователя в файл, принадлежащий первому зарегистрированному пользователю в приложении. После некоторой отладки выяснилось, что OutputStream изменяется только при 2 обстоятельствах: инициализации FileManager и ролловера. Затем принудительное переключение в пользовательской политике при изменении текущего пользователя, но в итоге после каждого рулона создавался новый файл, а не запись в ранее существовавшие, поэтому в течение 10 минут было около 20-30 разных файлов.
Итак, вопрос (ы): есть ли какой-либо способ заставить приложение использовать предыдущий файл, скажем, «для отката», а не только создавать новый?
Был ли мой подход неправильным?
Спасибо.
Комментарии:
1. Вероятно, вам следует изучить приложение RoutingAppender
2. Да, также пробовал что-то вроде следующего, но столкнулся с той же проблемой. <Имя маршрутизации =»Маршрутизация»> <Шаблон маршрутов =»$${ctx:userId}»> <Имя файла RollingFile=»rollingFileUser» FilePattern=»${Путь к журналу}/${Имя файла rollingFileName}_$${ctx:userId}%d{гггг-ММ-дд}_%i.txt «> <PatternLayout pattern=»${patternLogUser}» /> <Policies> <UserLoggingTriggerPolicy /> <TimeBasedTriggeringPolicy interval=»1″/> </Policies> <DirectWriteRolloverStrategy /> </RollingFile> </Routes </Routing> В любом случае спасибо.