Creating multiple log files of different content with log4j - java

Is there a way to configure log4j so that it outputs different levels of logging to different appenders?
I'm trying to set up multiple log files. The main log file would catch all INFO and above messages for all classes. (In development, it would catch all DEBUG and above messages, and TRACE for specific classes.)
Then, I would like to have a separate log file. That log file would catch all DEBUG messages for a specific subset of classes, and ignore all messages for any other class.
Is there a way to get what I'm after?

This should get you started:
log4j.rootLogger=QuietAppender, LoudAppender, TRACE
# setup A1
log4j.appender.QuietAppender=org.apache.log4j.RollingFileAppender
log4j.appender.QuietAppender.Threshold=INFO
log4j.appender.QuietAppender.File=quiet.log
...
# setup A2
log4j.appender.LoudAppender=org.apache.log4j.RollingFileAppender
log4j.appender.LoudAppender.Threshold=DEBUG
log4j.appender.LoudAppender.File=loud.log
...
log4j.logger.com.yourpackage.yourclazz=TRACE

Perhaps something like this?
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- general application log -->
<appender name="MainLogFile" class="org.apache.log4j.FileAppender">
<param name="File" value="server.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="FooLogFile" class="org.apache.log4j.FileAppender">
<param name="File" value="foo.log" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %t [%-40.40c] %x - %m%n"/>
</layout>
</appender>
<!-- foo logging -->
<logger name="com.example.foo">
<level value="DEBUG"/>
<appender-ref ref="FooLogFile"/>
</logger>
<!-- default logging -->
<root>
<level value="INFO"/>
<appender-ref ref="MainLogFile"/>
</root>
</log4j:configuration>
Thus, all info messages are written to server.log; by contrast, foo.log contains only com.example.foo messages, including debug-level messages.

I had this question, but with a twist - I was trying to log different content to different files. I had information for a LowLevel debug log, and a HighLevel user log. I wanted the LowLevel to go to only one file, and the HighLevel to go to both a file, and a syslogd.
My solution was to configure the 3 appenders, and then setup the logging like this:
log4j.threshold=ALL
log4j.rootLogger=,LowLogger
log4j.logger.HighLevel=ALL,Syslog,HighLogger
log4j.additivity.HighLevel=false
The part that was difficult for me to figure out was that the 'log4j.logger' could have multiple appenders listed. I was trying to do it one line at a time.
Hope this helps someone at some point!

For the main logfile/appender, set up a .Threshold = INFO to limit what is actually logged in the appender to INFO and above, regardless of whether or not the loggers have DEBUG, TRACE, etc, enabled.
As for catching DEBUG and nothing above that... you'd probably have to write a custom appender.
However I'd recommend not doing this, as it sounds like it would make troubleshooting and analysis pretty hard:
If your goal is to have a single file where you can look to troubleshoot something, then spanning your log data across different files will be annoying - unless you have a very regimented logging policy, you'll likely need content from both DEBUG and INFO to be able to trace execution of the problematic code effectively.
By still logging all of your debug messages, you are losing any performance gains you usually get in a production system by turning the logging (way) down.

Demo link: https://github.com/RazvanSebastian/spring_multiple_log_files_demo.git
My solution is based on XML configuration using spring-boot-starter-log4j. The example is a basic example using spring-boot-starter and the two Loggers writes into different log files.

Related

Weblogic12 + Log4j logging not writing to server logs

I know there are lots of Q's regarding this, but I did go through all of them, and kinda confused myself more, I am listing the steps I followed, please let me know where I messed it up.
1) I just want to use Log4j on application level, so need to copy WL_HOME/server/lib/wllog4j.jar, and the log4j.jar in Domail_Home/Lib?
2) I am using Maven, I added the Log4j dependency in my pom.xml [war].I have my WAR wrapped in EAR.
3) Since I want to write the logs in weblogic managed server logs file, I created a custom appender, to use weblogic, NonCatalogAppender as mention in the link - https://blog.desgrange.net/2010/02/15/logging-in-weblogic-console-with-log4j.html
4) I copied the log file in my war/src/main/resources and i see maven added them to classpath i.e war/target/classes, see below for my lo4j xml
http://jakarta.apache.org/log4j/'>
<!-- stdout appender settings -->
<appender name="STDOUT" class="com.xyz.logging.util.WeblogicAppender">
<param name="Threshold" value="DEBUG"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- notes on patterns:
%p - priority (i.e. level) of message
%c - class that threw error
%m - message in logger's method, e.g. "Exiting application HERE..."
%n - carriage return
%d - date information
-->
<param name="ConversionPattern" value="%c{1} %m"/>
</layout>
</appender>
<!-- settings for root debugger -->
<root>
<level value="DEBUG"/>
<appender-ref ref="STDOUT"/>
</root>
5) Now I didn't change anything on the config level, but I don't see anything appending to server logs. When I initialize NonCatlogLogger manually and call the logger it works fine:
NonCatalogLogger logger =new NonCatalogLogger("XYZ");
logger.debug("This is the debug message")
6) When I debug the application in eclipse, it looks like my custom appender is never called.
Got it, just need to put below into arguments under "server start".
-Dweblogic.log.Log4jLoggingEnabled=true

Best way to modify log4j appended for logging

I'm currently developing soon to be big(functional wise) rest web service and I want to capture logs really good, so I can have a good insight of what is going on where. For now I use log4j for logging, using this appended setting :
<!-- 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: %c - %m%n" />
</layout>
</appender>
which produces these kind of logs :
10:44:55,893 INFO [STDOUT] INFO : my.package.MyClass - I'm class message
How can I make this message look like i.e.
10:44:55,893 INFO : my.package.MyClass - I'm class message
Can I make a special appender or whatever it is, and use it in some classes not in all, i.e. I want to have in few of my logs this :
Payload: some request parameters
Response: some response that my service returns
extra data : some extra data
Without having these INFO [STDOUT] INFO my.package.MyClass in front of it
UPDATE
I forgot to mention in the question that I'm using Jboss 5. I think the jboss might be adding the 10:44:55,893 INFO [STDOUT] to any format that I put in my log4j config.
BOUNTY UPDATE
I changed this :
<!-- ============================== -->
<!-- Append messages to the console -->
<!-- ============================== -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
to this:
<!-- ============================== -->
<!-- Append messages to the console -->
<!-- ============================== -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%m%n"/>
</layout>
</appender>
And it worked, but it seems kind of ugly to do it like this. Is there any other way? I'm using spring MVC/JBoss combination.
I'm now getting nice clean messages :
10:44:55,893 INFO : my.package.MyClass - I'm class message
without annoying
10:44:55,893 INFO [STDOUT]
prefix
Question 1:
Use the following pattern layout for your appender:
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p: %c - %m%n" />
The conversion pattern in the configuration file you stated does not result in the kind of log you stated. For example the date/time is not included in your conversion pattern.
Question 2:
You can use a special logger which uses another appender that is only logging the pure message.
Your configuration would for example look like the 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="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n" />
</layout>
</appender>
<appender name="consoleAppender2" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p: %c - %m%n" />
</layout>
</appender>
<logger name="specialLogger" additivity="false">
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</logger>
<root>
<priority value="INFO" />
<appender-ref ref="consoleAppender2" />
</root>
</log4j:configuration>
You use the specialLogger for the pure messages without the additional information. It can be used in multiple classes.
In the configuration of the specialLogger, additivity = "false" is needed, because otherwise also the appender consoleAppender2 of the root logger would log the same message. (The message would be logged two times in this case.)
Your code could for example look like this:
public class TestClassA
{
private static Logger specialLogger = Logger.getLogger("specialLogger");
private static Logger logger = Logger.getLogger(TestClassA.class);
public TestClassA() {
}
public void doSomething() {
logger.info("Some message from TestClassA");
specialLogger.info("Some message via the specialLogger from TestClassA");
}
}
Calling doSomething results in:
17:17:18,125 INFO : com.foo.TestClassA - Some message from TestClassA
Some message via the specialLogger from TestClassA
Somewhere in your main class you need to configure log4j as usual, e.g.:
DOMConfigurator.configureAndWatch("log4j.xml", 60 * 1000);
The INFO [STDOUT] normally comes from log4j listening for System.out as well. We had a similiar case where the application itself had its own log4j configuration and thus got its own root appender. This would log to the console which is listened to by the JBoss log4j. This in turn adds the INFO [STDOUT] as if you were writing directly to System.out (or ERROR [STDERR] when writing to System.err).
The solution in our case was to remove the application specific log4j config and just use the one that JBoss writes to.
Another way might be to directly write to an application specific log file rather than writing to the console. In a server environment you'd most probably refer to log files anyway.
As for the second part, i.e. automatically extending logs with response, request etc. data:
In one case we had a super class for stateless session beans that provided logging functionality and had a (overwritable) logger per instance. The base methods like info would then call the logger and add the required data automatically.
A second approach could be MCD, i.e. you put some data (like the request) into the thread local MDC (basically a map) and then access them in your pattern definition.
For example, we have several similar applications each of which has some classes the others have too. So we'd need which application the message originated from and thus added the application name to the MDC:
In the code:
MDC.put("app.name", "myapplication");
In the log4j pattern config:
<param name="ConversionPattern" value="%d %-5p [%c (%X{app.name})] %m%n"/> (note the %X{app.name})
I didn't test whether you could do something like putting the request into the MDC and then use : %X{request.getAttribute('xyz')} but if it just gets the value in the MDC and calls toString() on it, you might create a request wrapper like this:
class RequestLogWrapper {
private HttpServletRequest request; //initialize through constructor etc.
public String toString() {
return request.getAttribute("xyz") + ";" + request.getAttribute("abc") + ... //handle null etc. as well
}
}
Then call MDC.put("request", new RequestLogWrapper(request)); and in the config use %X{request}.
Try to use this pattern as it will give you clean message:
<param name="ConversionPattern" value="%d{HH:mm:ss.SSS} %-5p %c %X %m/>
It is a good idea to add some unique value to MDC when request comes in, then add %X{uniqueValueKey} to your pattern. It will allow you to track logs for this unique request.
If you do not like the log4j xml configuration file you could switch to a property file instead. You cannot configure filters using the simple property file but since it seems you don't need them this shouldn't be an issue.
Given that you're
...currently developing soon to be big(functional wise) rest web service and I want to capture logs really good, so I can have a good insight of what is going on where.
then I'm afraid that your desired output won't give you many insights at all, it won't scale well, and it will make you loose your mind once the application gets big as expected...
Please refer to Log4j Best Practices for a good reference of logs design. Please take a look at ALL its paragraphs including the cosmetic consideration at the very end. Hope this helps.
to print only messages , the following conversion pattern will do.
<param name="ConversionPattern" value="%m%n"/>
Depending on your requirement, you can set the conversion pattern to whatever you want to
%-5p refers to the type of log entry. This would appear in the
log file as INFO, DEBUG, ERROR, etc. Technically, %p would be enough
to include this description; the -5 is there to include the word in
a 5-character width column.
%d refers to the date.
%t to the name of the thread that raised this log entry.
%c lists the category that generated this log which usually is the
class name.
%m displays the message
%n adds a carriage return.
Are you going to put all relevant information in messages only? I am not sure but its not a good idea.

Silencing Flyway -- a log4j problem

I've written a wrapper around Flyway I call Nomad. I am well pleased with Flyway, save the incessant logging it performs outside of Maven. I created an issue here. Each user of Nomad must make their own configuration of log4j to silence Flyway. This is problematic if not done, for instance, during Spec testing. However, getting the configuration just right is a challenge and, moreover, having to do this breaks the abstraction of my library.
My question is this: how can I permanently silence flyway so that any user of Nomad is not burdened with the task? I've found that this log4j.xml sometimes works:
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<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} %t %-5p %c{1} - %m%n"/>
</layout>
</appender>
<logger name="org.springframework" additivity="false">
<level value="error"/>
<appender-ref ref="console"/>
</logger>
<root>
<priority value="error"/>
<appender-ref ref="console"/>
</root>
</log4j:configuration>
This stifles Flyway to the point of being helpful, rather than overly chatty. The misdirection is still broken, but not often.
The way you have done it in log4j.xml seems good. I don't see anything wrong.
Since the project uses Maven, I recommend you adding a property file instead log4j.properties, that you place that in src/main/resources
The contents can be:
log4j.rootCategory=DEBUG, stderr
log4j.appender.stderr=org.apache.log4j.ConsoleAppender
log4j.appender.stderr.target=System.err
log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
log4j.appender.stderr.layout.ConversionPattern=[%d] %-5p %c %x: %m%n
# Silence springframework messages.
org.springframework=ERROR
Perhaps that will work better with you. It becomes easier to manage too.
Flyway's only non-logging framework dependency is Spring. As Mohamed Mansour pointed out you can suppress all but the ERROR messages with a simple Log4J configuration setting.
For Spring (as pointed out by Mohamed Mansour):
org.springframework=ERROR
For Flyway:
com.googlecode.flyway=ERROR

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)));

java logging nightmare and log4j not behaving as expected with spring + tomcat6

I have a spring application that has configured log4j (via xml) and that runs on Tomcat6 that was working fine until we add a bunch of dependencies via Maven. At some point the whole application just started logging part of what it was supposed to be declared into the log4.xml
"a small rant here" Why logging has to be that hard in java world? why suddenly an application that was just fine start behaving so weird and why it's so freaking hard to debug?
I've been reading and trying to solve this issue for days but so far no luck, hopefully some expert here can give me some insights on this
I've added log4j debug option to check whether log4j is taking reading the config file and its values and this is what part of it shows
log4j: Level value for org.springframework.web is [debug].
log4j: org.springframework.web level set to DEBUG
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [org.compass] additivity to [true].
log4j: Level value for org.compass is [debug].
log4j: org.compass level set to DEBUG
As you can see debug is enabled for compass and spring.web but it only shows "INFO" level for both packages. My log4j config file has nothing out of extraordinary just a plain ConsoleAppender
<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: %c - %m%n" />
</layout>
</appender>
What's the trick to make this work? What it's my misunderstanding here?
Can someone point me in the right direction and explain how can I make this logging mess more bullet proof?
It might not be log4j that is doing the logging, and hence your log4j config would be ignored. Spring logs using Commons Logging, which is an api that can delegate to various logging frameworks, including log4j. To decide which implementation to use, commons logging looks into the classpath.
If you have added a dependency that dragged its own logging implementation into the classpath, commons logging might now use the other implementation.
I recommend to set a breakpoint at a call to the logging facility, and trace the execution to see which logging implementation is used.
As it was working until you loaded a number of dependencies via Maven, perhaps there's a Log4j configuration loaded inadvertently via these dependencies ?
Run mvn dependency:tree to see what's being loaded, and then see if any of these dependencies has a Log4j configuration.
I think your problem is that you're not setting the threshold param on your appenders, and (maybe) because you're not assigning those appenders to your loggers.
Try adding param name="threshold" value="debug" to your appenders and then explicitly adding them to the specific (or root) loggers like so:
<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="%-5p: %c - %m%n" />
</layout>
</appender>
<logger name="org.springframework.web">
<level value="debug" />
<appender-ref ref="console" />
</logger>
Also, this page says "This appender will not log any messages with priority lower than the one specified here even if the category's priority is set lower" which is probably the source of your problem.
This seems like a good thread for you to read:
http://forum.springsource.org/showthread.php?t=88250
Cutting to the chase, it seem that the poster had a problem with a Tomcat security setting. An updated Tomcat policy file fixed the issue.
Probably has something do with reading outside of the webapp for your log4j.xml file.

Categories

Resources