Log4j2 using multiple appender and logger

2019-08-30 09:54发布

问题:

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.

回答1:

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>