Log4j2 using multiple appender and logger - java

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.

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>

Related

How can I use log4j with multiple use of appenders with dynamic filename?

I want to use an log4j-Appender multiple times, but with different filenames:
Appender:
<RollingFile name="MODULE" fileName="log/module-${ModuleName}.log" append="true" filePattern="log/module-${ModuleName}-%d{yyyy-MM-dd}_%i.log" >
<PatternLayout pattern="%d{yyyy/MM/dd-HH:mm:ss} %-5p %C:%M:%L ~ %m%n"/>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
Loggers:
<Logger name="MOD1" level="debug">
<Properties>
<Property name="ModuleName">MOD1</Property>
</Properties>
<appender-ref ref="MODULE"/>
</Logger>
<Logger name="MOD2" level="error">
<Properties>
<Property name="ModuleName">MOD2</Property>
</Properties>
<appender-ref ref="MODULE"/>
</Logger>
But this don't work. How can I pass a Variable from the Logger to the Appender?
Finally I want 2 Files
/log/module-MOD1.log <- Debug messages from MOD1
/log/module-MOD2.log <- Error messages from MOD2
Thanks for any help
Just add another Appender and connect Logger and Appender each pair.
For example :
...
<RollingFile name="MODULE1" fileName="./log/module1-${ModuleName}.log" append="true" filePattern="./log/module1-${ModuleName}-%d{yyyy-MM-dd}_%i.log" >
<PatternLayout pattern="%d{yyyy/MM/dd-HH:mm:ss} %-5p %C:%M:%L ~ %m%n"/>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile name="MODULE2" fileName="./log/module2-${ModuleName}.log" append="true" filePattern="./log/module2-${ModuleName}-%d{yyyy-MM-dd}_%i.log" >
<PatternLayout pattern="%d{yyyy/MM/dd-HH:mm:ss} %-5p %C:%M:%L ~ %m%n"/>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
...
...
<Logger name="com.foo.bar.ClassName1" level="debug">
<Properties>
<Property name="ModuleName">MOD1</Property>
</Properties>
<appender-ref ref="MODULE1"/>
</Logger>
<Logger name="com.foo.bar.ClassName2" level="error">
<Properties>
<Property name="ModuleName">MOD2</Property>
</Properties>
<appender-ref ref="MODULE2"/>
</Logger>
...
There was a same ask so I replied there too. so, please visit here.

Storm bolt always logs to worker.log

I have a storm bolt that is responsible for extracting the contents of an email. I would like to log some details about the email in a log file of my choosing instead of in worker.log. The bolt does log to worker.log for errors etc. and I want it to continue to do so.
I've updated the cluster.xml to include the new logger
<configuration monitorInterval="60" shutdownHook="disable">
<properties>
<property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} %c{1.} %t [%p] %msg%n</property>
</properties>
<appenders>
<RollingFile name="A1" immediateFlush="false"
fileName="${sys:storm.log.dir}/${sys:logfile.name}"
filePattern="${sys:storm.log.dir}/${sys:logfile.name}.%i.gz">
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<DefaultRolloverStrategy max="9"/>
</RollingFile>
<RollingFile name="TEST-SIZE" immediateFlush="false"
fileName="${sys:storm.log.dir}/test_debug.log"
filePattern="${sys:storm.log.dir}/test_debug.log.%i.gz">
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<DefaultRolloverStrategy max="9"/>
</RollingFile>
<Syslog name="syslog" format="RFC5424" charset="UTF-8" host="localhost" port="514"
protocol="UDP" appName="[${sys:daemon.name}]" mdcId="mdc" includeMDC="true"
facility="LOCAL5" enterpriseNumber="18060" newLine="true" exceptionPattern="%rEx{full}"
messageId="[${sys:user.name}:S0]" id="storm" immediateFlush="true" immediateFail="true"/>
</appenders>
<loggers>
<Logger name="TestSizeLogger" level="info" additivity="false">
<AppenderRef ref="TEST-SIZE"/>
<AppenderRef ref="syslog"/>
</Logger>
<root level="info"> <!-- We log everything -->
<appender-ref ref="A1"/>
<appender-ref ref="syslog"/>
</root>
</logger>
In my Java code I then create two logger instances but they both log to worker.log
static Logger logger = LoggerFactory.getLogger(ExtractorBolt.class);
static Logger testLogger = LoggerFactory.getLogger("TestSizeLogger");
I would appreciate any advice in regards to how I can get my testLogger to log to my new log file.
cluster.xml is for configuring the logging for Nimbus, the supervisor and other daemons. You should edit the log4j2/worker.xml file to configure worker logging.

ImmediateFlush not working in Log4j2

I am getting this error:
ERROR asyncRoot contains an invalid element or attribute "immediateFlush"
When I use immediateFlush attribute in appender in log4j2.xml.
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d{dd-MM-yy HH:mm:ss} [$${ctx:instId} - $${ctx:userId}] %c.%M(%L)- %m%n" />
</Console>
<RollingFile name="csroot"
fileName="${cslogs}/cslog.log" filePattern="${cslogs}/$${date:yyyy-MM}/cslog-%d{yyyy-MM-dd}-%i.log">
<PatternLayout pattern="%d{dd-MM-yy HH:mm:ss} [$${ctx:instId} - $${ctx:userId}] %c.%M(%L)- %m%n" immediateFlush="false"/>
<Policies>
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<DefaultRolloverStrategy max="1000">
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
Try with this modification:
<RollingFile name="csroot"
fileName="${cslogs}/cslog.log" filePattern="${cslogs}/$${date:yyyy-MM}/cslog-%d{yyyy-MM-dd}-%i.log" immediateFlush="false">
<PatternLayout pattern="%d{dd-MM-yy HH:mm:ss} [$${ctx:instId} - $${ctx:userId}] %c.%M(%L)- %m%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<DefaultRolloverStrategy max="1000">
</DefaultRolloverStrategy>
</RollingFile>
immediateFlush is not an attribute of PatternLayout.
I know its quite an old question but might help somebody.
RollingFile Appender Parameters points out the immediateFlush is the property of the appender. But you have it declared as an attribute for PatternLayout which is what is causing the error.
Sample RollingFile appender configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"
immediateFlush="false">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="250 MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>

how to configure log4j2 webapplication

Am little new to web applications, recently I was in need to employ a logging mechanism and for that I choose Log4J2, I went through there guide, and downloaded required libraries. This is what so far I did.
1. Added following jars to web-inf/lib
-- log4j-core2.1.jar
-- log4j-api-2.1.jar
-- log4j-web-2.1.jar
2. Added below xml as, log4j2.xml in java/src directory
<?xml version="1.0" encoding="UTF-8"?>
<configuration name="NONPROD" status="OFF">
<Properties>
<Property name="log-path">logs</Property>
</Properties>
<Appenders>
<Console name="console-log" target="SYSTEM_OUT">
<!-- <pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n -->
<!-- </pattern> -->
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<RollingFile name="info-log" fileName="${log-path}/web-info.log"
filePattern="${log-path}/web-info-%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
</RollingFile>
<RollingFile name="error-log" fileName="${log-path}/web-error.log"
filePattern="${log-path}/web-error-%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
</RollingFile>
<RollingFile name="debug-log" fileName="${log-path}/web-debug.log"
filePattern="${log-path}/web-debug-%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
</RollingFile>
<RollingFile name="trace-log" fileName="${log-path}/web-trace.log"
filePattern="${log-path}/web-trace-%d{yyyy-MM-dd}.log">
<PatternLayout>
<pattern>[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
<OnStartupTriggeringPolicy />
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.demo.web.log4j2.file" level="debug"
additivity="false">
<appender-ref ref="trace-log" level="trace" />
<appender-ref ref="error-log" level="error" />
<appender-ref ref="debug-log" level="debug" />
<appender-ref ref="info-log" level="info" />
</Logger>
<Logger name="com.demo.web.log4j2.console" level="all"
additivity="false">
<AppenderRef ref="console-log" />
</Logger>
<Root level="info" additivity="true">
<AppenderRef ref="console-log" />
</Root>
</Loggers>
</configuration>
3. third and last i wrote an small web service to test logging
#Path("/register")
public class Register {
private DataManager mManager;
private static final Logger LOG = LogManager.getLogger(Register.class);
public Register(){
mManager = DataManager.getInstance();
}
#GET
#Path("/{param}")
public Response getMsg(#PathParam("param") String msg) {
LOG.error("Not supported operations");
return Response.status(Response.Status.BAD_REQUEST)
.entity("Not supported").build();
}
But in console, upon trigger get request this is all i got printed.
INFO: Server startup in 35959 ms
Not supported operations // this is not in pattern i supplied in log4j2.xml
// this is my pattern
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
I figure out this is probably due to some thing gone wrong, and am struggling to find the actual cause, being totally new to web programming, please help me out to configure my logger.
Thanks,
Techfist
Your servlet container is using some other logging framework which logs to console. Figure out which logging framework that is and use one of log4j2's bridge libraries to redirect output to your log4j2 setup.
Alright, I found the cause behind this, Issue was primarily happening due to two reasons.
First I was suppose to exclude log4j* pattern from jarsToSkip attribute in catilina property
Second, i had kept two log4j2.xml one inside web-inf other inside java/src, it was supposed to be only present at java/src. two files were not required.
Third, but not mandatory, before deployment just check if log4j2.xml is included inside web-inf/classes or not, if not then simply add it.
that's it, after following this issue was resolved now am getting proper logs.

How does RollingFileAppender work with log4j2?

I'm use to RollingFileAppender on normal log4j. Now I'm switching to log4j2, and cannot get the appender to work.
The File appender below works as expected. But the logging file for RollingFile is never created. Why?
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="FILE" fileName="c:/logs.log">
<PatternLayout pattern="%d %p %c: %m%n" />
</File>
<RollingFile name="ROLLING" fileName="c:/logsroll.log">
<PatternLayout pattern="%d %p %c: %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="0.001 MB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="FILE" />
<AppenderRef ref="ROLLING" />
</Root>
</Loggers>
</Configuration>
The RollingFile tag is missing a filePattern attribute.
<RollingFile name="ROLLING"
fileName="c:/logsroll.log"
filePattern="c:/logsroll-%i.log">
I used log4j2 version 2.0, in some cases it throws error if you do not set any date in file pattern, in this case you can use some thing like below:
<RollingFile name="MyFile" fileName="d:/log/bsi/admin/total/totalLog.log"
filePattern="d:/log/totalLog-%d{MM-dd-yyyy}-%i.log">
<PatternLayout>
<Pattern>%d %p %c [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
<DefaultRolloverStrategy max="2000"/>
</RollingFile>

Categories