Log4j, disable appenders dependent on environment - java

I would like to have one log4j.xml config and be able to log to console while developing my application. Once deployed to an environment I want to only log to a file appender and not the console. How can I achieve this?
This is my current config:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="DEBUG" />
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss} %-5p%c{1} - %m%n" />
</layout>
</appender>
<appender name="LogFileAppender" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${log-base-dir}/${adapter-name}.log" />
<param name="MaxFileSize" value="5000KB" />
<param name="MaxBackupIndex" value="99" />
<param name="append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss} %-5p%c{1} - %m%n" />
</layout>
</appender>
<root>
<level value="info" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="LogFileAppender" />
</root>
</log4j:configuration>

One of the solutions could be separation of log4j configuration files for development and production environments e.g.:
log4j-development.xml - for development environment
log4j-production.xml - for production environment
Then your application startup command could have parrameter specifying log4j configuration file e.g. java -Dlog4jconfig=log4j-development.xml -jar Application.jar
You can configure log4j by getting value of log4jconfig property in your code e.g. System.getProperty("log4jconfig").
Pros of that solution are as follows:
You can specify loggers independently (ConsoleAppender and LogFileAppender in development and only LogFileAppender in production)
You can specify your logging level per environment (e.g. error in production and debug in development)
You can configure file logger independently e.g. keep logs for X days in production (for audit purposes etc.) and have only one log file in development etc.
That pattern is used in many application servers where you have multiple environments (Development, UAT, Staging, Production etc.)
Example of log4j-development.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="DEBUG" />
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss} %-5p%c{1} - %m%n" />
</layout>
</appender>
<root>
<level value="debug" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4j:configuration>
Example of log4j-production.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="LogFileAppender" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${log-base-dir}/${adapter-name}.log" />
<param name="MaxFileSize" value="5000KB" />
<param name="MaxBackupIndex" value="99" />
<param name="append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss} %-5p%c{1} - %m%n" />
</layout>
</appender>
<root>
<level value="error" />
<appender-ref ref="LogFileAppender" />
</root>
</log4j:configuration>

It is easy to do using appender's Threshold parameter and JVM system property. E.g.
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="${my.console.level}" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m%n" />
</layout>
</appender>
Then when starting application on prod use -Dmy.console.level=OFF
At the same time when starting locally use -Dmy.console.level=ALL
Both OFF and ALL are valid log4j levels.

With Log4j2 you could alternatively switch the appender reference with a Java system property like so:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
<Appenders>
<!-- Log file location uses Tomcat system variable, change for other web servers -->
<RollingFile name="rolling-file"/>
<Console name="console"/>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="${sys:log4j.loggers.root.appender:-rolling-file}"/>
</Root>
</Loggers>
</Configuration>
(the minus - in front of the default value in the sys prop variable is required for some reason)
To switch from the default "rolling-file" to the console"
-Dlog4j.loggers.root.appender=console

Related

log4j new log file is not creating when tomcat 7 starting in AWS server instance

I have implemented a log4j XML file to create a new log file.in my local machine, when the tomcat starts the java web application, log file is being created without any issue.but i have hosted my java web application in aws instance configured with tomcat 7.but when i logged to aws instance and check tomcat log folder grid-services.log file cannot be located.can anyone tell why this happened?
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="false">
<appender name="default.console" class="org.apache.log4j.ConsoleAppender">
<param name="target" value="System.out" />
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
</layout>
</appender>
<appender name="default.file" class="org.apache.log4j.FileAppender">
<param name="file" value="${catalina.home}/logs/grid-services.log" />
<param name="append" value="false" />
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
</layout>
</appender>
<logger name="com.customer"
additivity="false">
<level value="info" />
<appender-ref ref="default.file" />
</logger>
<root>
<priority value="info" />
<appender-ref ref="default.console" />
<appender-ref ref="default.file" />
</root>
</log4j:configuration>
Look in your ${TOMCAT_HOME}/bin/catalina.sh. Check if the
-Dcatalina.home=
variable is set on your aws instance.

How to create different files for logger hierarchy in tomcat?

In my Tomcat application, I want to use two loggers to log general event informations and errors to two different files.
Logger eventLogger = Logger.getLogger("event");
Logger errorLogger = Logger.getLogger("error");
Now I want to do the following: the logs of the eventLogger should be written to a "events.log" file, and the errorLogger logs should be written in a "errors.log" file. All logs from any other logger (e.g. Tomcat logs) should be written to catalina.out (or any other default file).
How can I achive this with JULI? Or do I need a third party lib?
This can't be achieved with Juli. You might use log4j.
Basically you need appenders. They will manage the logs to go to separate files. Example configuration in xml:
<?xml version="1.0"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.EnhancedPatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%t][%c{1}:%L] %m%n" />
</layout>
</appender>
<appender name="eventFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="#tomcat.home#/logs/event.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
</layout>
</appender>
<appender name="errorFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="#tomcat.home#/logs/error.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
</layout>
</appender>
<logger name="event" additivity="false">
<level value="INFO" />
<appender-ref ref="eventFILE" />
</logger>
<logger name="error" additivity="false">
<level value="INFO" />
<appender-ref ref="errorFILE" />
</logger>
<root>
<priority value="INFO" />
<appender-ref ref="FILE" />
</root>
</log4j:configuration>
you have to define an appender for each file in your log4j.xml and connect them to your loggers:
<?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="%d{ISO8601} %5p [%c.%M:%L] - %m%n" />
</layout>
</appender>
<appender name="FILE-error" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="${catalina.base}/logs/error.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="ImmediateFlush" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %5p [%c.%M:%L] - %m%n" />
</layout>
</appender>
<appender name="FILE-event" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="${catalina.base}/logs/event.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="ImmediateFlush" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss};%m%n" />
</layout>
</appender>
<!-- Loggers -->
<logger name="error" additivity="false">
<level value="warn" />
<appender-ref ref="FILE-error" />
</logger>
<logger name="event" additivity="false">
<level value="info" />
<appender-ref ref="FILE-event" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="FILE-error" />
</root>
</log4j:configuration>
Tomcat documentation does not provide any way to define more than one file per application when using JULI. Actually it provides the steps to use log4j instead of it because JULI configuration can be too basic.
But again this configuration is at container level:
Note: The steps described in this section are needed when you want to
reconfigure Tomcat to use Apache log4j for its own logging. These
steps are not needed if you just want to use log4j in your own web
application. — In that case, just put log4j.jar and log4j.properties
into WEB-INF/lib and WEB-INF/classes of your web application.
So using a third party library is the logical choice and you can find how to configure it in this SO post
Tomcat JULI logging supports this only via the logging.properties located in the ${catalina.base}/config folder.
#Declares the handlers allowed for use.
handlers = 100catalina.org.apache.juli.FileHandler, 200catalina.org.apache.juli.FileHandler, 300catalina.org.apache.juli.FileHandler
#Install the 'all' hander on the root logger.
.handlers=300catalina.org.apache.juli.FileHandler
#Install the 'event' handler on the 'event' logger and don't report to root.
event.handlers=100catalina.org.apache.juli.FileHandler
event.useParentHandlers=false
#Install the 'error' handler on the 'error' logger and don't report to root.
error.handlers=200catalina.org.apache.juli.FileHandler
error.useParentHandlers=false
#Event handler settings.
100catalina.org.apache.juli.FileHandler.level = ALL
100catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
100catalina.org.apache.juli.FileHandler.prefix = event.
#Error handler settings.
200catalina.org.apache.juli.FileHandler.level = ALL
200catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
200catalina.org.apache.juli.FileHandler.prefix = error.
#Root handler settings.
300catalina.org.apache.juli.FileHandler.level = ALL
300catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
300catalina.org.apache.juli.FileHandler.prefix = all.
This config will not work if you try to install this file in the WEB-INF/classes/logging.properties. This is because the ClassLoaderLogManager doesn't allow you to install handlers on named loggers.

Trouble with log4j configuration

I have been trying to change the logging from console to both console as well as file. Looking at the large documentation on log4j I was able to add the appender as shown in the code below. However I don't seem to be getting logs in the specified file.
Any ideas what might be wrong? Here is my log4j.xml (already located at src/)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="DEBUG"/>
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.RollingFileAppender">
<param name="append" value="false" />
<param name="file" value="/data/MFlogs/log.log"/>
<param name="immediateFlush" value="true"/>
<param name="threshold" value="debug"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<root>
<priority value="DEBUG" />
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</log4j:configuration>
change file path tag. try it with double slash.
value="//data//MFlogs//log.log"
Try adding full path to path location or add ${catalina.home}/logs/myApp.log to it.
Read this question, it tells how to use relative path. It is easy if you use properties file instead of xml file.

log4j prints debug to file, but not info

I am able to print debug logs to a file, but I am unable to print info. However, printing info and debug to console works correctly. How do I go about getting info to print in a file as well?
Thanks
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value= "%-5p [%t]: %m%n"/>
</layout>
</appender>
<appender name="R" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="example.log"/>
<param name="MaxFileSize" value="1000000KB"/>
<param name="MaxBackupIndex" value="1"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value= "%-5p [%t]: %m%n"/>
</layout>
</appender>
<root>
<priority value="info" />
<appender-ref ref="stdout" />
<appender-ref ref="R" />
</root>
</log4j:configuration>
So I was using the java logger object rather than the apache4j logger object...

Spring Batch: Logs not written in log file in AfterJob Method

I'm facing a problem with the logs when I'm launching the Job on Unix, actually the log file contains all the informations except those that I write in the log in a JobExecutionListener and exactly in the AfterJob Method.
When I'm using Eclipse I can see the report lines in the console.
Here is the configuration of log4j
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="appenderConsole" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-6p [%-25c{1}] %m%n" />
</layout>
</appender>
<appender name="traceDefaultAppender" class="org.apache.log4j.FileAppender">
<param name="file" value="log.tmp"/>
<param name="encoding" value="ISO-8859-1" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-6p [%-25c{1}] %m%n" />
</layout>
</appender>
<appender name="reportDefaultAppender" class="org.apache.log4j.FileAppender">
<param name="file" value="log.tmp"/>
<param name="encoding" value="ISO-8859-1" />
<param name="threshold" value="REPORT#com.cegedimactiv.fwb.core.business.log.LevelReport"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n" />
</layout>
</appender>
<logger name="defaultLogger">
<level value="INFO" />
<appender-ref ref="traceDefaultAppender" />
<appender-ref ref="reportDefaultAppender" />
</logger>
<root>
<level value="INFO"/>
<appender-ref ref="appenderConsole" />
</root>
</log4j:configuration>
Any Idea?

Categories

Resources