How to configure log4j to enable/disable logging to a file? - java

I've written up a small console utility. Throughout the application, I have used slf4j/log4j to log debug, trace, info statements to the console as I was developing it. Now that I am done development and want to release it, I would like to disable all output to the console except for a couple of specific loggers and send all the remaining loggers to a text file.
In theory, this should be fairly easy. I have created 2 appenders (one ConsoleAppender and one FileAppender). I have assocaited the ConsoleAppender with the specific loggers want on the Console and the FileAppender at the Root level. This works fine.
My issue now, is if I want to completely disable the FileAppender, I cannot figure out how to do it. If I add a DenyAllFilter to the FileAppender, it will prevent anything from being written to the file, but the file is still created. If I remove the FileAppender from the ROOT logger, I get Log4J writting to StdErr:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
If I set the ROOT level to OFF, the individual loggers that I have set custom debug levels to still output.
If I set the LoggerRepository Level to OFF, then all loggers (those I want to go to STDOUT and the File) are all shut off.
Is there any way to do this easily? Ideally, I want to be able to disable the file appender altogether, however provide a command line switch to enable it if desired.
<?xml version="1.0" encoding="UTF-8" ?>
<!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="%d{ISO8601} %-5p %c{5} - %X{messageId} - %m%n" />
<!-- <param name="ConversionPattern" value="%m%n" /> -->
</layout>
</appender>
<appender name="LOGTXT" class="org.apache.log4j.FileAppender">
<param name="file" value="lss-client.log" />
<param name="append" value="false" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %-5p %c{5} - %X{messageId} - %m%n" />
</layout>
<!-- <filter class="org.apache.log4j.varia.DenyAllFilter"/> -->
</appender>
<!-- Spring Loggers -->
<logger name="org.springframework">
<level value="INFO" />
</logger>
<logger name="org.springframework.ws.client.MessageTracing.sent">
<level value="TRACE" />
</logger>
<logger name="org.springframework.ws.client.MessageTracing.received">
<level value="TRACE" />
</logger>
<logger name="com.cws.cs.Client" >
<level value="INFO" />
<appender-ref ref="STDOUT" />
</logger>
<root>
<level value="INFO" />
<appender-ref ref="LOGTXT" />
</root>
</log4j:configuration>
Thanks!
Eric

Pretty sure Slf4J/Log4J creates the log file immediately when you configure a FileAppender.
I think your best bet here is to have 2 different and complete Log4J configurations and pick which one you load at startup based on your command line parameter.
In PseudoCode:
public static void main(String[] args){
//if log to file arg = true
DOMConfigurator.configure("logToFile.log4j.xml");
//else
DOMConfigurator.configure("logToConsoleOnly.log4j.xml");
}
Edit
Furthermore, if you don't like the idea of maintaining two configuration files. You could create one configuration with the common components (probably the spring stuff and w/e else) and then based on your parameter, programatically configure the FileAppender:
public static void main(String[] args){
DOMConfigurator.configure("log4j.xml");
//if log to file arg = true{
// Define layout
PatternLayout layout = new PatternLayout();
layout.setConversionPattern("%d{ISO8601} %-5p %c{5} - %X{messageId} - %m%n");
// Create appender
FileAppender appender = new FileAppender();
appender.setFile("lss-client.log");
appender.setLayout(layout);
appender.activateOptions();
// Get root logger and add appender.
log = Logger.getRootLogger();
log.setLevel(Level.INFO);
log.addAppender(appender);
}
}

Related

Ways to configure logs other than log4j xml, properties file, and source code (mainly java)?

I'm looking at the source code of some application. It is using Spring framework, Apache Tiles, JSP, Log4j, java, javascript, jquery, jqplot, Jsch, and etc.
I know where the logs are created. (a/b/logs) However, when I look at source code, I don't know how logs are created under the folder name 'logs'. I looked at log4j.xml, web.xml , property files. I found the code for how the path 'a/b' is created, but not logs. Also that folder has 4 types of logs. And they are name in a pattern like access.20181227001 , errors.20182111. I want to know where I have to look to find how the logs are created in this manner.
Log4J.xml
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p [%c] %m%n" />
</layout>
</appender>
<appender name="console-infolog" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p %m%n" />
</layout>
</appender>
<!-- Application Loggers -->
<logger name="com.dsmentoring.chakan" additivity="false">
<level value="debug" />
<appender-ref ref="console"/>
</logger>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="error"/>
</logger>
<!-- Bean logger -->
<logger name="org.springframework.beans">
<level value="error"/>
</logger>
<!-- Context logger -->
<logger name="org.springframework.context">
<level value="error"/>
</logger>
<!-- Web logger -->
<logger name="org.springframework.web">
<level value="error"/>
</logger>
<logger name="org.springframework.ldap" additivity="true">
<level value="error"/>
</logger>
<!-- LDAP logger -->
<logger name="com.unboundid.ldap" additivity="true">
<level value="error"/>
</logger>
<!-- Root Logger -->
<root>
<priority value="off" />
<appender-ref ref="console" />
</root>
To sum up :
1) Is there a way to configure where logs are created and how they are created (4 types of logs) Other than log4j.xml, xml files and property files? I looked at all the java, jsp, js code but can't seem to find the configuration for logs. So I want to know if there are other ways to do that or where I should look for those configuration.
2) The 'logs' folder is possibly default for log4j?
ldap.properties
#LDAP Connection Info
ldap.host=192.168.0.17
ldap.port=22389
ldap.userName=cn=directory manager
ldap.password= 9074B18A0DE2D50C068D37B60BE5DFDE
ldap.baseDN=o=sso30root
ldap.defaultLoadSize=1000
ldap.start=start-ds
ldap.stop=stop-ds
ldap.workdir=/home/KB_openDJ // logs are created under this path
// /home/KB_openDJ/logs
In other java class, they use this.
#Value("${ldap.workdir}")
private String WORK_DIR;
// I ommited many lines in between
try{
diskUsage = sigar.getFileSystemUsage(WORK_DIR);
diskIOInfo.setDiskRead((int)(diskUsage.getDiskReadBytes()));
diskIOInfo.setDiskWrite((int)(diskUsage.getDiskWriteBytes()));
}catch(SigarException sigarEx){
log.debug("Disk Usage info load Error : " + sigarEx.getMessage());
}
I used the 'Search' feature in Eclipse many times. ( logs, WORK_DIR, and 4 types of log name, and many others. I am unable to locate the code about logging configuration. :(
My log4j version :
1.2.15
Ok, it seems that there's a solution which might help you. It requires some debugging of static initalization block of org.apache.log4j.LogManager class. This class is responsible for loading logger configuration file. Here's a documention link which thoroughly describes initalization process: link.
Here's an excerpt from a LogManager source file:
String configurationOptionStr = OptionConverter.getSystemProperty(DEFAULT_CONFIGURATION_KEY, null);
String configuratorClassName = OptionConverter.getSystemProperty(CONFIGURATOR_CLASS_KEY, null);
What I'm trying to show you here, is that your logger configuration file might be specified as a JVM option supplied to your application-server. That's why you are not able to determine actual file being used.
Even if this approach fails, I'd recommend you to investigate the appenders list retrieved at run-time. Here's a stackoverflow thread which describes how to do so: link.

How to prevent log4j logs from being redirected to root logger

I have only two loggers defined : one is root logger and another one is common logger.
I think then common logger becomes immediate child of root logger right?
if yes, then how to prevent logs printed by common logger's appender to bubble up to root logger's appender?
according to docs :
However, if an ancestor of logger C say P, has the additivity flag set
to false, then C's output will be directed to all the appenders in C
and its ancestors upto and including P but not the appenders in any of
the ancestors of P.
means the logger whose additivity is set to false will have all its logs to be bubbled up to
its parent but not above that. Am i correct?
If yes then setting additivity flag of my common logger wouldn't help(in fact it doesn't :)) and the logs are still printed to both common and root logger. How to prevent this?
#root logger config starts
log4j.rootLogger=INFO, RA
log4j.appender.RA=org.apache.log4j.RollingFileAppender
log4j.appender.RA.File=/Data/var/logs/root.log
log4j.appender.RA.MaxFileSize=100KB
# Keep one backup file
log4j.appender.RA.MaxBackupIndex=1
log4j.appender.RA.layout=org.apache.log4j.PatternLayout
log4j.appender.RA.layout.ConversionPattern=%p %d - %m%n
# root config logger ends
#ico common logger config starts
log4j.logger.com=INFO, COMMONA
log4j.appender.COMMONA=org.apache.log4j.RollingFileAppender
log4j.additivity.com=false
log4j.appender.COMMONA.File=/Data/var/logs/common_ico.log
log4j.appender.COMMONA.MaxFileSize=100KB
# Keep one backup file
log4j.appender.COMMONA.MaxBackupIndex=1
log4j.appender.COMMONA.layout=org.apache.log4j.PatternLayout
log4j.appender.COMMONA.layout.ConversionPattern=[%x]%p %d - %m%n
#ico common logger config ends
Above config works. I was using log4j.additivity.COMMONA=false instead of log4j.additivity.com=false
with this config
<appender name="a2" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="common %m%n" />
</layout>
</appender>
<appender name="a1" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="root %m%n" />
</layout>
</appender>
<logger name="common" additivity="false">
<appender-ref ref="a2" />
</logger>
<root>
<priority value="debug" />
<appender-ref ref="a1" />
</root>
this
Logger.getLogger("common").debug("1111");
prints
common 1111

How to get other than root logger from SLF4J using Log4J

I am learning Slf4j and log4j in Spring.I have seen that eyerywhere we are using one line
private final Logger logger = LoggerFactory.getLogger(name.class);
I have seen that this is getting root logger by default.
How this is getting root logger?Am I wrong?
How can i get other loggers which are defined in log4j.xml file?
This is my configuration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC
"-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %5p %c{2}: %m%n" />
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</appender>
<appender name="FILE" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="C:/log/spring-hib.log" />
<param name="MaxBackupIndex" value="100" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %5p %c{2}: %m%n" />
</layout>
</appender>
<logger name="com.example.foo">
<level value="DEBUG"/>
<appender-ref ref="FooLogFile"/>
</logger>
<category name="org.hibernate">
<priority value="DEBUG" />
</category>
<category name="java.sql">
<priority value="debug" />
</category>
<root>
<priority value="INFO" />
<appender-ref ref="ASYNC" />
</root>
</log4j:configuration>
I have seen that this is getting root logger by default
No it is not.
Assume FQN of Name is foo.bar.Name), when you call private final Logger logger = LoggerFactory.getLogger(Name.class); , you are getting a logger with name foo.bar.Name, for which inherits from foo.bar, for which inherits from foo, for which inherits from root.
You can get the root logger in SLF4J by LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)
Loggers are hierarchical. Child level logger inherits configurations from its parent (including appenders, level etc). I believe you were confused about "getting a child logger which inherited config from ROOT logger" and "getting the ROOT logger"
2.How can i get other loggers which are defined in log4j.xml file?
For example, if you want to get logger com.example.foo, it is simply by private final Logger logger = LoggerFactory.getLogger("com.example.foo");
As mentioned above, loggers are hierarchical. If you get the logger "com.example.foo.Bar", given there are no specific setting for "com.example.foo.Bar", its behaviour should be the same as using "com.example.foo" (except the logger name being show in log of course).
As it is a common practice to use the class name itself as the logger name, SLF4J also provide a method to get logger by providing a class (as what you do in your question), by Logger logger = LoggerFactory.getLogger(Bar.class);. This make it more refactoring-friendly. In this case, the logger name got will be the same as the FQN of the class provided ("com.example.foo.Bar")
1.How this is getting root logger
Loggers build a hierarchy, as you can see from the tables here: http://logging.apache.org/log4j/2.x/manual/architecture.html
2.How can i get other loggers which are defined in log4j.xml file?
If you want strictly what's defined there, than you have to parse and read that config file.
If you need all the active loggers and their configuration at runtime, than there's API for it. E.g. an article how to do it: http://nelz.net/2008/04/08/log4j-runtime-configuration/
Also,I havent found any good tutorial on slf4J.If you have some good links
slf4j has quite a few docs: http://www.slf4j.org/docs.html but since it's just a wrapper,
log4j does the "work" so here's a book about it: http://www.qos.ch/shop/products/log4jManual

Logging different Level messages in different Logs using Log4j

I want to maintain two Log Files in my web-application using apache Log4j.jar:
1) One log will contain all the Log messages of every level
2) Second log file will contain the Log messages of specific class
This is the configuration XML that I am using: (Not much aware of the tags used in the XML, was just trying out)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="FILE1" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="D:/CSVExportLogs/CSVExportLogFile-ERROR.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c (%F:%L) - %m%n"/>
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="D:/CSVExportLogs/CSVExportLogFile-INFO.log"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c (%F:%L) - %m%n"/>
</layout>
</appender>
<category name="com.taxware.mgmt.CustomerManager" additivity="false">
<priority value="warn"/>
<appender-ref ref="FILE"/>
</category>
<root>
<priority value="info"/>
<appender-ref ref="FILE1"/>
</root>
</log4j:configuration>
By the above xml I am getting only info messages in the FILE1, I want messages of all levels as well as the message of warn level that are going in the separate file in this file. Is there any solution available for this.
# Create ROOT logger(main logger) with level INFO, and add to it 2 appenders:
# FILE_INFO, FILE_WARN. This means that all loggers by default will writes messages
# in this 2 file appenders, with level INFO or higher
log4j.rootLogger=INFO, FILE_INFO, FILE_WARN
######## LEVELS:
# Set logging level to WARN for all classes and subclasses in package
# com.taxware.mgmt.CustomerManager
log4j.category.com.taxware.mgmt.CustomerManager=WARN
######## APPENDERS:
# FILE_INFO
# Type of appender
log4j.appender.FILE_INFO=org.apache.log4j.RollingFileAppender
# File where to save all messages
log4j.appender.FILE_INFO.File=D:/CSVExportLogs/CSVExportLogFile-INFO.log
# Max file size, after that will be created new log file, and old file will be renamed
log4j.appender.FILE_INFO.MaxFileSize=100KB
# Maximum amount of old log files.
log4j.appender.FILE_INFO.MaxBackupIndex=100
# Patter of messages.
log4j.appender.FILE_INFO.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE_INFO.layout.ConversionPattern=%d{ISO8601} [%-5p][%-24.24t][%32.32c] - %m%n
# Custom level for appender. In this file will be add only messages with level INFO or highter
log4j.appender.FILE_INFO.Threshold=INFO
# FILE_WARN file appender
log4j.appender.FILE_WARN=org.apache.log4j.RollingFileAppender
log4j.appender.FILE_WARN.File=D:/CSVExportLogs/CSVExportLogFile-WARN.log
log4j.appender.FILE_WARN.MaxFileSize=50KB
log4j.appender.FILE_WARN.MaxBackupIndex=10
log4j.appender.FILE_WARN.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE_WARN.layout.ConversionPattern=%d{ISO8601} [%-5p][%-24.24t][%32.32c] - %m%n
# Custom level for appender. In this file will be add only messages with level WARN or highter
log4j.appender.FILE_WARN.Threshold=WARN
For logging the messages of specific class you could do following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="myClassAppender" class="org.apache.log4j.FileAppender">
<param name="File" value="../logs/myClassLogs.log"/>
<param name="Append" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n"/>
</layout>
</appender>
.............
<logger name="com.my.package.MySpecificClass">
<!--
all log messages of level "debug" or higher will be logged, unless defined otherwise
all log messages for "MySpecificClass" will be logged to the appender "myClassAppender"
-->
<level value="DEBUG"/>
<appender-ref ref="myClassAppender"/>
</logger>
.............
</log4j:configuration>
Here is the link.
http://veerasundar.com/blog/2011/05/log4j-tutorial-writing-different-log-levels-in-different-log-files/
I say this act in log4j levels:
All < Debug < Info < Warn < Error < Fatal < Off
With your configuration, happen thease:
All logs with "com.taxware.mgmt.CustomerManager" category and "Warn" and smaller level("Error" < Fatal) send for "FILE" appender and don't send for "FILE" appender because you set additivity attribute to false for it.
All logs with any category except "com.taxware.mgmt.CustomerManager" send for "FILE1" appender.
3.You say:"By the above xml I am getting only info messages in the FILE1". You trying logging log with "Warn" or smaller levels(Such as "Error") and "com.taxware.mgmt.CustomerManager" category, you will see result in "FILE" appender and also trying logging with another category and you will see result in "FILE1" appender, except this result is wrong. please do this and say result.
I also suggest you use SLF4J for decoupling API and implementation.

Log4j: How to configure simplest possible file logging?

My story:
I want to make a thing which is as simple as a simplest possible log4j logger that logs rows to a file. I have found several examples with some functionality, but not a basic, general one that really works, and not one with an explanation how the each row work.
Question:
Could anybody provide one?
Prerequisites:
I already know where to put the file and I have the log4j configured and working for console logging.
Now I want to log to a file and also find the file from file system once the program has run.
Rows needed to be added to the existing log4j.properties file are the desired output.
I have one generic log4j.xml file for you:
<?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="/log/mylogfile.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>
<appender name="another.file" class="org.apache.log4j.FileAppender">
<param name="file" value="/log/anotherlogfile.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.yourcompany.SomeClass" additivity="false">
<level value="debug" />
<appender-ref ref="another.file" />
</logger>
<root>
<priority value="info" />
<appender-ref ref="default.console" />
<appender-ref ref="default.file" />
</root>
</log4j:configuration>
with one console, two file appender and one logger poiting to the second file appender instead of the first.
EDIT
In one of the older projects I have found a simple log4j.properties file:
# For the general syntax of property based configuration files see
# the documentation of org.apache.log4j.PropertyConfigurator.
# The root category uses two appenders: default.out and default.file.
# The first one gathers all log output, the latter only starting with
# the priority INFO.
# The root priority is DEBUG, so that all classes can be logged unless
# defined otherwise in more specific properties.
log4j.rootLogger=DEBUG, default.out, default.file
# System.out.println appender for all classes
log4j.appender.default.out=org.apache.log4j.ConsoleAppender
log4j.appender.default.out.threshold=DEBUG
log4j.appender.default.out.layout=org.apache.log4j.PatternLayout
log4j.appender.default.out.layout.ConversionPattern=%-5p %c: %m%n
log4j.appender.default.file=org.apache.log4j.FileAppender
log4j.appender.default.file.append=true
log4j.appender.default.file.file=/log/mylogfile.log
log4j.appender.default.file.threshold=INFO
log4j.appender.default.file.layout=org.apache.log4j.PatternLayout
log4j.appender.default.file.layout.ConversionPattern=%-5p %c: %m%n
For the description of all the layout arguments look here: log4j PatternLayout arguments
<?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="fileAppender" class="org.apache.log4j.RollingFileAppender">
<param name="Threshold" value="INFO" />
<param name="File" value="sample.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" />
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="fileAppender" />
</root>
</log4j:configuration>
Log4j can be a bit confusing. So lets try to understand what is going on in this file:
In log4j you have two basic constructs appenders and loggers.
Appenders define how and where things are appended. Will it be logged to a file, to the console, to a database, etc.? In this case you are specifying that log statements directed to fileAppender will be put in the file sample.log using the pattern specified in the layout tags. You could just as easily create a appender for the console or the database. Where the console appender would specify things like the layout on the screen and the database appender would have connection details and table names.
Loggers respond to logging events as they bubble up. If an event catches the interest of a specific logger it will invoke its attached appenders. In the example below you have only one logger the root logger - which responds to all logging events by default. In addition to the root logger you can specify more specific loggers that respond to events from specific packages. These loggers can have their own appenders specified using the appender-ref tags or will otherwise inherit the appenders from the root logger. Using more specific loggers allows you to fine tune the logging level on specific packages or to direct certain packages to other appenders.
So what this file is saying is:
Create a fileAppender that logs to
file sample.log
Attach that appender to the root
logger.
The root logger will respond to any
events at least as detailed as
'debug' level
The appender is configured to only
log events that are at least as
detailed as 'info'
The net out is that if you have a logger.debug("blah blah") in your code it will get ignored. A logger.info("Blah blah"); will output to sample.log.
The snippet below could be added to the file above with the log4j tags. This logger would inherit the appenders from <root> but would limit the all logging events from the package org.springframework to those logged at level info or above.
<!-- Example Package level Logger -->
<logger name="org.springframework">
<level value="info"/>
</logger>
Here's a simple one that I often use:
# Set up logging to include a file record of the output
# Note: the file is always created, even if there is
# no actual output.
log4j.rootLogger=error, stdout, R
# Log format to standard out
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %5p\t[%d] [%t] (%F:%L)\n \t%m%n\n
# File based log output
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=owls_conditions.log
log4j.appender.R.MaxFileSize=10000KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern= %5p\t[%d] [%t] (%F:%L)\n \t%m%n\n
The format of the log is as follows:
ERROR [2009-09-13 09:56:01,760] [main] (RDFDefaultErrorHandler.java:44)
http://www.xfront.com/owl/ontologies/camera/#(line 1 column 1): Content is not allowed in prolog.
Such a format is defined by the string %5p\t[%d] [%t] (%F:%L)\n \t%m%n\n. You can read the meaning of conversion characters in log4j javadoc for PatternLayout.
Included comments should help in understanding what it does. Further notes:
it logs both to console and to file; in this case the file is named owls_conditions.log: change it according to your needs;
files are rotated when they reach 10000KB, and one back-up file is kept
Here is a log4j.properties file that I've used with great success.
logDir=/var/log/myapp
log4j.rootLogger=INFO, stdout
#log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.DailyRollingFileAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{MM/dd/yyyy hh:mm:ss a}|%-5p|%-30c{1}| %m%n
log4j.appender.stdout.DatePattern='.'yyyy-MM-dd
log4j.appender.stdout.File=${logDir}/myapp.log
log4j.appender.stdout.append=true
The DailyRollingFileAppender will create new files each day with file names that look like this:
myapp.log.2017-01-27
myapp.log.2017-01-28
myapp.log.2017-01-29
myapp.log <-- today's log
Each entry in the log file will will have this format:
01/30/2017 12:59:47 AM|INFO |Component1 | calling foobar(): userId=123, returning totalSent=1
01/30/2017 12:59:47 AM|INFO |Component2 | count=1 > 0, calling fooBar()
Set the location of the above file by using -Dlog4j.configuration, as mentioned in this posting:
java -Dlog4j.configuration=file:/home/myapp/config/log4j.properties com.foobar.myapp
In your Java code, be sure to set the name of each software component when you instantiate your logger object. I also like to log to both the log file and standard output, so I wrote this small function.
private static final Logger LOGGER = Logger.getLogger("Component1");
public static void log(org.apache.log4j.Logger logger, String message) {
logger.info(message);
System.out.printf("%s\n", message);
}
public static String stackTraceToString(Exception ex) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
return sw.toString();
}
And then call it like so:
LOGGER.info(String.format("Exception occurred: %s", stackTraceToString(ex)));

Categories

Resources