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.
Related
This is my log4j.xml. i want only FATAL log from package com.xyz.rest should print to /LOGS/Acb/d.log file.
But i can see Debug level logs as well in file. Why log4j is printing Debug level logs from com.xyz.rest package.
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="Def" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="/LOGS/Acb/d.log"/>
<param name="MaxFileSize" value="10000KB"/>
<param name="MaxBackupIndex" value="10"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<logger name="com.xyz.rest">
<logger value="fatal"/>
<appender-ref ref="Def"/>
</logger>
</log4j:configuration>
Its because with the following code you are adding another log level to your com.xyz.rest package which is not removing the debug level which your package inherits from parents:
<logger name="com.xyz.rest">
<logger value="fatal"/>
<appender-ref ref="Def"/>
</logger>
What you need is to set the additivity to false so that rather than adding another log level, you will set the log level:
<logger name="com.xyz.rest" additivity="false">
<logger value="fatal"/>
<appender-ref ref="Def"/>
</logger>
More information can be found here.
Not sure but it might also be necessary to enclose the <logger></logger> tags in <loggers></loggers> tag
Before with one class, logging was working well, but after I added 2nd Java class, it is logging twice in this second class. Can anyone help me, how to make it log only once. The problem seems to be in this log4j.xml file, because if I comment out appender, it is logging once, but I don't want to change the code in log4j sufficiently, because then I am afraid logging will not work properly in the 1st class.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<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: [%d{MMM-dd HH:mm:ss,SSS}] %c{3} - %m%n"/>
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.FileAppender">
<param name="file" value="/user/Dave/log.out"/>
<param name="immediateFlush" value="true"/>
<param name="threshold" value="debug"/>
<param name="append" value="false"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: [%d{MMM-dd HH:mm:ss,SSS}] %c{3} - %m%n"/>
</layout>
</appender>
<logger name="com.asaqa.score">
<level value="all"/>
</logger>
<!-- Root Logger -->
<root>
<priority value="error"/>
<appender-ref ref="console"/>
</root>
</log4j:configuration>
By default loggers inherit appenders, and each appender creates log entries. In your case the "com.asaqa.score" logger inherits from root. You can turn this off by setting additivity to false. And you should complete the config of your logger to include an appender
<logger name="com.asaqa.score" additivity="false">
<level value="all"/>
<appender-ref ref="console"/>
</logger>
Also, the error below suggests you're using the old version of log4j. You may want to consider upgrading to log4j 2. In fact, it's recommended by Apache themselves.
On August 5, 2015 the Logging Services Project Management Committee announced that Log4j 1.x had reached end of life. For complete text of the announcement please see the Apache Blog. Users of Log4j 1 are recommended to upgrade to Apache Log4j 2.
When you do, note that there are some changes to the config syntax.
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.
I want to redirect log to specific log file, by classname. The intention is to have a group of classes log output to a specific log file.
Right now the all output comes to console, and on startup it throws and error saying log4j:ERROR Could not retrieve category [com.mycomp]. Reported error follows..
What am I doing wrong here?
In my java class :-
private static final Logger log = Logger.getLogger(SpringBootLog4jApplication.class.getName());
My log4j.xml :-
<?xml version="1.0" encoding="UTF-8" ?>
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' debug="false">
<appender name="LOGFILE" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="/git/services.log"/>
<param name="maxBackupIndex" value="10"/>
<param name="maxFileSize" value="20MB"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %x %p %c{1} :: %m\n"/>
</layout>
</appender>
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<!-- Pattern to output the caller's file name and line number -->
<param name="ConversionPattern" value="%5p [%t] (%F:%L) - %m%n"/>
</layout>
</appender>
<logger name="com.mycomp" class="com.mycomp.SpringBootLog4jApplication" additivity="false">
<level value="INFO"/>
<appender-ref ref="LOGFILE"/>
</logger>
<root>
<level value="INFO"/>
<appender-ref ref="stdout"/>
</root>
I believe that the name for the logger should look like
<logger name="com.mycomp.*"...
as that would resolve to any concrete classes in the package.
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>