Log4j: specific logging - java

I have a service class that import and parse files from an ftp server.
This task can be executed from a Spring controller when the user choose a specific action.
The same service is used by a scheduled task (TimerTask) that everyday at a specific time do the same.
I would separate logging for user / scheduled execution into different files:
logs/scheduledImport.log
logs/userImport.log
Is it possible with Log4j?

Of course. First you must define 2 different file appenders.
<appender name="default.file" class="org.apache.log4j.FileAppender">
<param name="file" value="/log/userImport.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
</layout>
</appender>
<appender name="another.file" class="org.apache.log4j.FileAppender">
<param name="file" value="/log/scheduledImport.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
</layout>
</appender>
Then you define your loggers:
<logger name="com.foo.UserService" additivity="false">
<level value="debug" />
<appender-ref ref="default.file" />
</logger>
<logger name="com.foo.ScheduledService" additivity="false">
<level value="debug" />
<appender-ref ref="another.file" />
</logger>

You can use different loggger instances. In this case you can apply different settings (output file) for each logger.

Related

log4j level trace and debug didn't show any log

In log4j there are level from trace at the lowest, debug, info, warn, error, and fatal.
I used level info to log my web application with this code
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="abclog" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="/data/abc/abc.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
</appender>
<logger name="com.myapp">
<level value="info" />
<appender-ref ref="abclog"/>
</logger>
<logger name="com.myapp.controller">
<level value="info" />
<appender-ref ref="abclog"/>
</logger>
</log4j:configuration>
It'd produce abc.log contained log from level info to fatal.
Then I tried to move the error log only to another file, error.log.
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="errorlog" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="/data/abc/error.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
</appender>
<appender name="abclog" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="/data/abc/abc.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
</appender>
<logger name="com.myapp">
<level value="error" />
<appender-ref ref="errorlog"/>
</logger>
<logger name="com.myapp.controller">
<level value="error" />
<appender-ref ref="errorlog"/>
</logger>
<logger name="com.myapp">
<level value="info" />
<appender-ref ref="abclog"/>
</logger>
<logger name="com.myapp.controller">
<level value="info" />
<appender-ref ref="abclog"/>
</logger>
</log4j:configuration>
But didn't work, all logger still in abc.log. I found that the logger outputs all those messages equal to that level and also all greater levels than it, that's why the log still in abc.log.
When I deleted abclog and log level info, it worked. It'd show logger from level error (and maybe fatal error if any) on error.log.
But why when I tried to lower the log info to trace / debug without level info or error, it didn't come up with anything, no logger created.
When I put the lowest log4j level, it should show all the log from its level and above like it supposed to do at info level (show log from info to fatal).
Why could it show up with nothing when the level change into trace / debug instead of level info?
Does it really no other way to separate error log to another file from other log?
Try to use the category with additivity set to false. I have not tested, but something like the following should work:
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="errorlog" class="org.apache.log4j.DailyRollingFileAppender">
<param name="Threshold" value="ERROR"/>
<param name="File" value="/data/abc/error.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
</appender>
<appender name="abclog" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="/data/abc/abc.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
</appender>
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
</appender>
<!-- all error from com.myapp to errorlog only -->
<category name="com.myapp" additivity="false">
<priority value="error" />
<appender-ref ref="errorlog"/>
</category>
<!-- all other log from com.myapp to abclog only -->
<category name="com.myapp" additivity="false">
<priority value="info" />
<appender-ref ref="abclog"/>
</category>
<root>
<!-- all other log to console -->
<appender-ref ref="console"/>
</root>
</log4j:configuration>
If you want to separate com.myapp and com.myapp.controller, you can declare more categories. But you should declare com.myapp.controller before com.myapp.
UPDATE : you can try with filter perhaps is what you need, after that, I have no more idea:
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="errorlog" class="org.apache.log4j.DailyRollingFileAppender">
<param name="Threshold" value="ERROR"/>
<param name="File" value="/data/abc/error.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="ERROR" />
<param name="levelMax" value="FATAL" />
</filter>
</appender>
<appender name="abclog" class="org.apache.log4j.DailyRollingFileAppender">
<param name="Threshold" value="INFO"/>
<param name="File" value="/data/abc/abc.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="INFO" />
<param name="levelMax" value="WARN" />
</filter>
</appender>
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}] [%-5p] [%t] {%F:%M:%L} - %m%n"/>
</layout>
</appender>
<!-- all log from com.myapp to special log file -->
<category name="com.myapp" additivity="false">
<appender-ref ref="errorlog"/>
<appender-ref ref="abclog"/>
</category>
<root>
<appender-ref ref="console"/>
</root>
</log4j:configuration>

Log4j debug to file - Info to console

I'm using log4j for logs.
I have a class that i want to print to the console only log.info level,
And print to some file log.info + log.debug levels (The same class).
I tried to setup the log4j.xml as follows :
<!--appender to parser file-->
<appender name="parserFile" class="org.apache.log4j.FileAppender">
<param name="File" value="/var/log/java/parser/parser.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{E MMM dd HH:mm:ss} %c : %m%n" />
</layout>
</appender>
<!--appender to the stdout-->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<logger name="parser.ParserMainJava">
<level value="debug" />
<appender-ref ref="parserFile" />
</logger>
<logger name="parser.ParserMainJava">
<level value="info" />
<appender-ref ref="console" />
</logger>
This is my configuration but I can't use 2 loggers with the same package name.
Any suggestions ?
Thanks,
Or.
Just define one logger for "parser.ParserMainJava" with debug level, and add the following parameter to your console appender definition:
<param name="Threshold" value="INFO"/>
In my case I needed to adjust my AppenderRef. Adding the param element to the ConsoleAppender did not work. This element inside Loggers is good.
<Root level="debug">
<AppenderRef ref="FileAppender" />
<AppenderRef ref="ConsoleAppender" level="info"/>
</Root>

How to conveniently store common logs and client specific logs

I have a huge code base which serves info requests about colleges. There is a base framework code, and we have some separate packages for college1, college2, etc.,
Whenever there is a request for some info about college X, both framework code and college specific code both are triggered. I want to see logs generated for all requests for Company X to go to one location, and company Y to go to one location.
How do I use JUL or apache's logging.properties file to achieve this ? How do I ensure logs written by common framework libraries for company X go to one location, and logs written by common framework libraries for company Y go to some other location ?
I would have an xml file that contain the appenders to specify what packages go into what log file.
You can then load the xml file in your application entry point. Below is an example I have used in my current project
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<param name="threshold" value="error" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%t] %p %c - %m%n" />
</layout>
</appender>
<appender name="codebaseXAppender" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="codebaseX.log" />
<param name="MaxFileSize" value="10MB" />
<param name="MaxBackupIndex" value="10"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%t] %d %p %c - %m%n"/>
</layout>
</appender>
<appender name="codebaseYAppender" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="codebaseY.log" />
<param name="MaxFileSize" value="10MB" />
<param name="MaxBackupIndex" value="10"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%t] %d %p %c - %m%n"/>
</layout>
</appender>
<!-- Root Logger -->
<root>
<priority value="error" />
<appender-ref ref="console" />
</root>
<!-- Application logger -->
<logger name="com.codebasePackageX" additivity="true">
<level value="info" />
<appender-ref ref="codebaseXAppender" />
</logger>
<!-- Application logger -->
<logger name="com.codebasePackageY" additivity="true">
<level value="info" />
<appender-ref ref="codebaseYAppender" />
</logger>
</log4j:configuration>

log4j log one class [duplicate]

I want to set up log4j so that all log meessages produced from classes under package com.foo.bar go to bar.log, and all the log meessages produced from classes under package com.bar.blatz go to blatz.log.
Questions
How do I do this using log4j.xml?
I know its possible using property files, but how do I do it using the XML configuration?
This is based on my answer to a similar question:
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- general application log -->
<appender name="BarLogFile" class="org.apache.log4j.FileAppender">
<param name="File" value="bar.log" />
<param name="Threshold" value="INFO" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %t [%-40.40c] %x - %m%n"/>
</layout>
</appender>
<!-- additional fooSystem logging -->
<appender name="BlatzLogFile" class="org.apache.log4j.FileAppender">
<param name="File" value="blatz.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %t [%-40.40c] %x - %m%n"/>
</layout>
</appender>
<logger name="com.foo.bar">
<appender-ref ref="BarLogFile"/>
</logger>
<logger name="com.bar.blatz">
<appender-ref ref="BlatzLogFile"/>
</logger>
<root>
<level value="INFO"/>
<!-- no appender, output will be swallowed (I think) -->
</root>
</log4j:configuration>
If you add an appender-ref to the root element, it will also receive com.foo.bar etc messages. You can stop that by specifying 'additivity="false"' on the loggers.
<root>
<level value="INFO"/>
<!-- no appender, output will be swallowed (I think) -->
</root>
We can add appenders here. It will work if the application is using root logger. for example quartz Scheduler API.

Log4j not printing 3rd party logs(Spring.Hibernate etc) to RollingFileAppender

I have been on log4j for sometime and read quite a few articles and all look pretty straight forward but when I implement it, it doesnt seem to work.
I have the below requirement :
1-> Need to have 2 files created for 2 different packages :
So I created as per log4j specs and it creates 2 files based on 2 different packages but only the logs logged from our application gets logged into those files.
The logs generated from Spring or Hibernate and Ibatis do not get logged to the file at all, but they get and all other logs do get logged to the console.
I am placing the log4j.xml that I am using, any help would be appreciated :
Also I have tried lots of combinations like from root appender removed the references already mentioned in the logger, adding them back to the root, add addivity to loggers but nothing worked:
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} DSL Service(CONSOLE) %-5p %c [%t]: %m%n%n"/>
</layout>
</appender>
<appender name="FEPOCServiceLog"
class="org.apache.log4j.RollingFileAppender">
<param name="Append" value="true"/>
<param name="maxFileSize" value="100KB" />
<param name="maxBackupIndex" value="5" />
<param name="File" value="C:\\tmp\\DSLService_1.0.log" />
<param name="threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{ISO8601} DService(CONSOLE) %-5p %c [%t]: %m%n%n" />
</layout>
</appender>
<appender name="iServiceLog"
class="org.apache.log4j.RollingFileAppender">
<param name="maxFileSize" value="10MB" />
<param name="maxBackupIndex" value="5" />
<param name="File" value="C:\\tmp\\iService_1.0.log" />
<param name="threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{ISO8601} iService(CONSOLE) %-5p %c [%t]: %m%n%n" />
</layout>
</appender>
Hope this helps :
<logger name="com.fepoc.services.dataservice">
<level value="DEBUG"/>
<appender-ref ref="FEPOCServiceLog"/>
</logger>
<logger name="com.fepoc.mpbit">
<level value="DEBUG"/>
<appender-ref ref="iServiceLog"/>
</logger>
<logger name="net.sf.hibernate">
<level value="DEBUG"/>
<appender-ref ref="FEPOCServiceLog"/>
</logger>
<logger name="org.hibernate">
<level value="DEBUG"/>
<appender-ref ref="FEPOCServiceLog"/>
</logger>
<logger name="com.mchange.v2">
<level value="DEBUG"/>
<appender-ref ref="FEPOCServiceLog"/>
</logger>
<logger name="com.ibatis.sqlmap">
<level value="DEBUG"/>
<appender-ref ref="FEPOCServiceLog"/>
</logger>
<logger name="org.springframework">
<level value="DEBUG"/>
<appender-ref ref="FEPOCServiceLog"/>
</logger>
...
<root>
<priority value ="debug" />
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="FEPOCServiceLog"/>
<appender-ref ref="iServiceLog"/>
Thanks,
NK
The problem is that Spring and Hibernate don't use log4j.
Hibernate internally uses slf4j, so you need to add slf4j-log4j binding to your classpath in order to redirect its output to log4j, see SLF4J user manual.
Spring uses Commons Logging, you can redirect its output to log4j via slf4j by adding jcl-slf4j bridge and slf4j-log4j binding, see Logging Dependencies in Spring.

Categories