Log4j2:如何为每个用户将日志写入单独的文件?
Posted
技术标签:
【中文标题】Log4j2:如何为每个用户将日志写入单独的文件?【英文标题】:Log4j2: How to write logs to separate files for each user? 【发布时间】:2014-09-26 16:21:30 【问题描述】:这是我面临的挑战:
我有一个 servlet 程序。我需要将每个用户的日志写入以该用户命名的文件夹。 像这样的:
// stores message to David folder
// /root_path/David/logfile.log
logger.error(MarkerManager.getMarker("David"), "Error happened");
// stores message to Mark folder
// /root_path/Mark/logfile.log
logger.error(MarkerManager.getMarker("Mark"), "Something is broken");
在我的示例中,我使用了标记。但我真的不知道标记是否适合这项任务。
一般来说,我的 appender 应该表现得像 RollingRandomAccessFile appender。 我猜 appender 的配置必须是这样的:
<RollingRandomAccessFile name="rollingFile"
fileName="logs/markerName ?????/movie-db.log"
filePattern="logs/log-%dyyyy-MM-dd-%i.log.zip"
append="false"
immediateFlush="false"
ignoreExceptions="true">
<PatternLayout pattern="%dISO8601 %levellength=5 [%thread] %logger - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="25 MB"/>
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingRandomAccessFile>
有什么想法吗?
【问题讨论】:
【参考方案1】:感谢@Remko Popma 的回答,我明白了。以下是解决方案示例:
package com.bondarenko.tmp;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
public class TestRouting
private final static Logger log = LogManager.getLogger(TestRouting.class);
public static void main(String[] args)
ThreadContext.put("logFileName", "David");
log.info("Error happened");
ThreadContext.put("logFileName", "Mark");
log.info("Something is broken");
ThreadContext.remove("logFileName");
还有log4j.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Appenders>
<Console name="consoleAppender" target="SYSTEM_OUT">
<!--SHORT PATTERN-->
<PatternLayout pattern="%dABSOLUTE %levellength=5 [%thread] %logger1 - %msg%n"/>
<!--ROBUST PATTERN
<PatternLayout pattern="%dISO8601 %levellength=5 [%thread] %logger - %msg%n"/>-->
</Console>
<Routing name="RoutingAppender">
<Routes pattern="$ctx:logFileName">
<Route>
<RollingFile name="Rolling-$ctx:logFileName"
fileName="logs/$ctx:logFileName"
filePattern="logs/$ctx:logFileName.%i.log.gz">
<PatternLayout pattern="%dABSOLUTE %levellength=5 [%thread] %logger1 - %msg%n"/>
<SizeBasedTriggeringPolicy size="512" />
</RollingFile>
</Route>
<!-- By having this set to $ctx:logFileName it will match when filename
is not set in the context -->
<Route ref="consoleAppender" key="$ctx:logFileName"/>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Logger name="com.bondarenko.tmp" level="info" additivity="false">
<AppenderRef ref="RoutingAppender"/>
</Logger>
</Loggers>
【讨论】:
谢谢!你太棒了! :) 将您的示例与常见问题解答页面 (logging.apache.org/log4j/2.0/faq.html#separate_log_files) 进行比较,您似乎需要Unable to create file /var/lib/tomcat8/logs/business_system/$ctx:userId/log.log java.io.IOException: The filename, directory name, or volume label syntax is incorrect
当使用 rollingFile 名称时 - /var/lib/tomcat8/logs/business_system/$$ctx:userId/log.log
【参考方案2】:
Log4j2 FAQ page 有一个使用 RoutingAppender 实现此目的的示例。
【讨论】:
谢谢。而已。虽然,仍然存在几个问题:我使用 tomcat 作为我的 servlet 容器,所以: - 我应该何时何地调用 ThreadContext.remove("logFileName")? - 如何确保调用上述方法? - 我应该为此烦恼吗? 在您的请求过滤器中 我总是对示例中的双 $$ 和单 $ 感到困惑,使用哪一个? 只是在模式中我们将 $ 转义为 $? 这是一个单独的 *** 问题的好候选人!以上是关于Log4j2:如何为每个用户将日志写入单独的文件?的主要内容,如果未能解决你的问题,请参考以下文章