【问题标题】:Log4j2: How to write logs to separate files for each user?Log4j2:如何为每个用户将日志写入单独的文件?
【发布时间】: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-%d{yyyy-MM-dd}-%i.log.zip"
                 append="false"
                 immediateFlush="false"
                 ignoreExceptions="true">
        <PatternLayout pattern="%d{ISO8601} %level{length=5} [%thread] %logger - %msg%n"/>
        <Policies>
            <SizeBasedTriggeringPolicy size="25 MB"/>
            <TimeBasedTriggeringPolicy />
        </Policies>
        <DefaultRolloverStrategy max="10"/>
    </RollingRandomAccessFile>

有什么想法吗?

【问题讨论】:

    标签: java logging configuration log4j log4j2


    【解决方案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="%d{ABSOLUTE} %level{length=5} [%thread] %logger{1} - %msg%n"/>
            <!--ROBUST PATTERN
            <PatternLayout pattern="%d{ISO8601} %level{length=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="%d{ABSOLUTE} %level{length=5} [%thread] %logger{1} - %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) 进行比较,您似乎需要 而不是 ,对吗?
    • 绝招:
    • 警告:“Route”、“ThreadContext”和朋友是 Log4j 2.0 的特性。如果您遇到像 Log4j 1.2 这样的旧版本,您将无法使用它们 :(
    • 我收到一个错误:- 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")? - 如何确保调用上述方法? - 我应该为此烦恼吗?
    • 在您的请求过滤器中
    • 我总是对示例中的双 $$ 和单 $ 感到困惑,使用哪一个?
    • 只是在模式中我们将 $ 转义为​​ $?
    • 这是一个单独的 StackOverflow 问题的好候选人!
    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多