0

I need to implement multiple loggers and multiple appenders. My log4j2.xml looks like below:

  <Appenders>
  <RollingFile name="SYSTEM_LOGGER"
                 fileName="${logging.folder}System.log"
                 filePattern="${ARCHIVE}System.log.%d{dd MMM yyyy HH:mm:ss.SSS}.gz">
        <PatternLayout>
        <Pattern>${PATTERN}</Pattern>
        </PatternLayout>
        <Policies>
            <TimeBasedTriggeringPolicy interval="10" modulate="true"/>
            <SizeBasedTriggeringPolicy size="4 MB" />
            <DefaultRolloverStrategy max="50"/>             
        </Policies>
    </RollingFile>

<Appenders>
<RollingFile name="COMMONREQ_LOGGER"
                 fileName="${logging.folder}/CommonReq.log"
                 filePattern="${ARCHIVE}/CommonReq.log.%d{dd MMM yyyy HH:mm:ss.SSS}.gz">
        <PatternLayout>
        <Pattern>${PATTERN}</Pattern>
        </PatternLayout>
        <Policies>
            <TimeBasedTriggeringPolicy interval="10" modulate="true"/>
            <SizeBasedTriggeringPolicy size="4 MB" />
            <DefaultRolloverStrategy max="50"/>             
        </Policies>
    </RollingFile>

<Appenders>
<RollingFile name="COMMONRES_LOGGER"
                 fileName="${logging.folder}/CommonRes.log"
                 filePattern="${ARCHIVE}/CommonRes.log.%d{dd MMM yyyy HH:mm:ss.SSS}.gz">
        <PatternLayout>
        <Pattern>${PATTERN}</Pattern>
        </PatternLayout>
        <Policies>
            <TimeBasedTriggeringPolicy interval="10" modulate="true"/>
            <SizeBasedTriggeringPolicy size="4 MB" />
            <DefaultRolloverStrategy max="50"/>             
        </Policies>
    </RollingFile>

  <Loggers>
    <Root level="INFO">
        <AppenderRef ref="SYSTEM_LOGGER"/>
        <AppenderRef ref="COMMONREQ_LOGGER"/>
        <AppenderRef ref="COMMONRES_LOGGER"/>
</Root>
</Loggers>

Now, when I execute the code using this xml, the log is written to the last log file CommonRes.log. I'm new to log4j. How can I write only to the desired log file?

EDIT:

This is what I have done so far in log4j2.xml:

  <Routing name="Routing">
  <Routes pattern="$${ctx:ROUTINGKEY}"> 
  <Route key="$${ctx:ROUTINGKEY}" >
  <RollingFile name="SYSTEM_LOGGER"
                 fileName="${logging.folder}/$${ctx:ROUTINGKEY}.log"
                 filePattern="${ARCHIVE}/$${ctx:ROUTINGKEY}.log.%d{dd MMM yyyy HH:mm:ss.SSS}.gz">
         <PatternLayout>
         <Pattern>${PATTERN}</Pattern>
         </PatternLayout>
         <Policies>
             <TimeBasedTriggeringPolicy interval="10" modulate="true"/>
             <SizeBasedTriggeringPolicy size="4 MB"/>
             <DefaultRolloverStrategy max="50"/>                
         </Policies>
     </RollingFile>
 </Route>
 </Routes>
 </Routing>
<Loggers>
    <Root level="INFO">  
        <AppenderRef ref="Routing" />
    </Root>

And in my java code:

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    logger = LogManager.getLogger(request.getPathInfo().replace("/", ""));
...
if(logger.getLevel() != null){
                    ThreadContext.put("ROUTINGKEY",  request.getPathInfo().replace("/", ""));

logger.info(contents);                                      
                    } 
  }

When I run the above code, it doesn't write to any file, instead gives the following error:

ERROR Unknown object "Routing" of type org.apache.logging.log4j.core.appender.routing.RoutingAppender is ignored.
ERROR Unable to locate appender Routing for logger  

Please help.

cleo
  • 1
  • 1
  • 2

1 Answers1

0

You can define multiple routes in the configuration, and put values in the ThreadContext map that determine which log file subsequent events in this thread get logged to. THIS LINK is where you can start from.

The basic concept is depending upon values in your threadcontext map, you can route your logs to different files. For example:

<Routing name="Routing">
        <Routes pattern="$${ctx:variable}"> 
            <!-- This route is chosen if thread context has no value for key 'variable' -->
            <Route key="$${ctx:variable}">
                <RollingFile name="Rolling-default" fileName="default.log"
                             filePattern="./logs/${date:yyyy-MM}/default-%d{yyyy-MM-dd}-%i.log.gz">
                    <PatternLayout>
                        <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern>
                    </PatternLayout>
                    <Policies>
                        <TimeBasedTriggeringPolicy interval="6" modulate="true" />
                        <SizeBasedTriggeringPolicy size="10 MB" />
                    </Policies>

                </RollingFile>
            </Route>

            <!-- This route is chosen if thread context has some value for key 'variable' -->       
            <Route>
                <File name="variable-${ctx:variable}" fileName="other.log">

                </File>
            </Route>
        </Routes>
    </Routing> 

fileName="default.log" and fileName="other.log" is your file path for your respective routes EDIT: Add one appender only. Depending upon thread context variable it will write to different file

<Loggers>
    <Root level="info">
        <AppenderRef ref="Routing" />
    </Root>
</Loggers>
pratim_b
  • 1,160
  • 10
  • 29
  • Thanks patim_b, i tried the same too, but it didint work. I tested some more and observed, it is always writing to the last appender in the log4j2 xml. Please suggest some other way. – cleo Sep 11 '15 at 08:07
  • You don't need to have multiple appenders, depending upon threadcontext variable, it will write to different files. See my edit – pratim_b Sep 11 '15 at 10:00
  • Where do I need to add key in ThreadContext Map? Can I do it just before writing the contents to log file ie. like: ThreadContext.put("ROUTINGKEY", request.getPathInfo().replace("/", "")); logger.info(contents); Please confirm. – cleo Sep 11 '15 at 11:20
  • You have defined only one route i,e only if the key exists. And yes Just before writing the log. That variable has the life span of thread unless you remove it. By the way, you dont define your path in your java code. – pratim_b Sep 11 '15 at 14:04
  • I have set the property for log path in log4j2.xml as: D:/logs %-5level %d [%t] %c:%M(%L): %m%n – cleo Sep 14 '15 at 10:13