Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log4j2: How to write logs to separate files for each user?

Here is the challenge I'm facing:

I have a servlet program. And I need to write logs for each user to the folder named after that user. Something like this:

    // 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");

In my example I used markers. But I don't really know whether markers appropriate for this task.

In general my appender should behave like RollingRandomAccessFile appender. I guess config for appender must look like something like this:

     <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>

Any ideas?

like image 516
Yurii Bondarenko Avatar asked Aug 04 '14 08:08

Yurii Bondarenko


People also ask

What is rolling file in Log4j2?

Log4j2 RollingFileAppender is an OutputStreamAppender that writes log messages to files, following a configured triggering policy about when a rollover (backup) should occur. It also has a configured rollover strategy about how to rollover the file.

What is rollover strategy in Log4j2?

Default Rollover Strategy. The default rollover strategy accepts both a date/time pattern and an integer from the filePattern attribute specified on the RollingFileAppender itself. If the date/time pattern is present it will be replaced with the current date and time values.

What are logging Appenders?

The appender is the part of a logging system that's responsible for sending the log messages to some destination or medium. It answers the question "where do you want to store this stuff?"

What is pattern layout in Log4j2?

Layout class and overrides the format() method to structure the logging information according to a supplied pattern. PatternLayout is also a simple Layout object that provides the following-Bean Property which can be set using the configuration file: Sr.No.


2 Answers

Thanks to @Remko Popma answer I figure it out. Here is the solution example:

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");
}
}

And 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>

like image 117
Yurii Bondarenko Avatar answered Sep 23 '22 11:09

Yurii Bondarenko


The Log4j2 FAQ page has an example that uses the RoutingAppender to achieve this.

like image 40
Remko Popma Avatar answered Sep 22 '22 11:09

Remko Popma