| <html> |
| <head> |
| <title>Troubleshooting log4j</title> |
| </head> |
| <body bgcolor=#FFFFFF> |
| |
| <h1 align=center>Log4j troubleshooting</h1> |
| |
| <h2 align=center>Ceki Gülcü Paul Glezen |
| <br/>February 2002 |
| </h2> |
| |
| <hr/> |
| |
| <p>Here is a list of commonly encountered problems when using log4j:</p> |
| |
| <ul> |
| |
| <li><p><a href=#noAppenders>log4j tells me to initialize |
| properly.</a></p> |
| </li> |
| |
| <li><p><a href=#duplicates>Duplicates in log4j output.</a></p> |
| </li> |
| <li><p><a href=#space>Options are not parsed correctly.</a></p> |
| </li> |
| <li><p><a href=#jit>Caller location information is printed as a "?" |
| character.</a> |
| </p> |
| </li> |
| |
| <li><p><a href=#cce>ClassCastException when instantiating a Category subclasses.</a> |
| </p> |
| </li> |
| |
| |
| <li><p><a href="#notfound">My EJB-Servlet-JSP says log4j class |
| not found or not defined.</a> </a></p> |
| </li> |
| |
| <li><p><a href=#syslogd>I cannot connect to syslogd under linux.</a> |
| </p></li> |
| |
| <li><p><a href="#nosuchpropperty">log4j:WARN No such property |
| [xyz] in some.appender.or.layout</a> |
| </p> |
| </li> |
| </ul> |
| |
| <hr> |
| |
| <p><a name="noAppenders"></a><h4>log4j tells me to initialize properly.</h4> |
| |
| Logging output is written to a target by using an appender. If no |
| appenders are attached to a category nor to any of its ancestors, you |
| will get the following message when trying to log: |
| </p> |
| |
| <pre> |
| log4j: No appenders could be found for category (some.category.name). |
| log4j: Please initialize the log4j system properly. |
| </pre> |
| |
| <p><em>Log4j does not have a default logging target.</em> |
| It is the user's responsibility to ensure that all |
| categories can inherit an appender. This can be easily |
| achieved by attaching an appender to the root category.</p> |
| |
| |
| <p><a name=duplicates></a><h3>Duplicates in log4j output.</h3></p> |
| |
| <p>The reason for observing duplicates in log4j output is |
| either due to having added the same appender multiple times |
| to the same category (typically root) or having added the |
| same appender to different categories ignoring the fact that |
| appenders are inherited cumulatively.</p> |
| |
| <p>log4j does not eliminate appender duplicates. In other |
| words, if you add the same appender to a category <i>n</i> |
| times, that appender will be invoked <i>n</i> times to |
| append to its target. </p> |
| |
| <p>A slightly different cause is adding different appenders |
| all sharing the same underlying output target to some |
| category. In the most common occurrence of this phenomenon, |
| the BasicConfigurator.configure() method is invoked multiple |
| times. Each time it is invoked, this method adds an appender |
| with a <code>System.out</code> target to the root |
| category. </p> |
| |
| <p>One other common mistake is to forget that appenders are |
| inherited cumulatively from the hierarchy. For example, if |
| you add an appender, say <code>A</code>, to the root |
| category, all other categories will inherit <code>A</code> |
| as an appender. Thus, if you add <code>A</code> to a |
| category, say <code>C</code>, then an enabled statement of |
| category <code>C</code>, will print to <code>A</code> twice, |
| once because <code>A</code> is in root and once because it |
| is in <code>C</code>. </p> |
| |
| <p><a name=space></a><h3>Options are not parsed correctly.</h3> |
| |
| <p>The PropertyConfigurator relies on |
| <code>java.util.Properties</code> class to read in the |
| configuration file. This class preserves spaces in |
| options. For example,</p> |
| |
| <pre> |
| fruit=orange |
| </pre> |
| is returned as an option having the key <code>"fruit"</code> and the |
| value <code>"orange "</code>.</p> |
| |
| <p>The spaces in the value, i.e. <code>"orange "</code>, are due to |
| invisible spaces at the end of the example shown above. Thus, some of |
| the options might not be interpreted correctly due to trailing |
| spaces. </p> |
| |
| <p><a name=jit></a><h3>Caller location information is printed as a "?" |
| character.</h3> |
| |
| Location information is extracted automatically by the PatternLayout |
| conversion patterns %C, %F, %M and %L. However, some just-in-time |
| (JIT) compilers make it impossible to extract location information. It |
| is also possible that the compiler that generated the byte code may |
| have omitted the LineNumber table as is done by -O option of javac |
| and jikes. </p> |
| |
| <p>You can remedy this problem by disabling the JIT compiler and by |
| compiling the code without the -O option.</p> |
| |
| <p><b>In wrappers or subclasses of Category </b> |
| |
| <p>Wrappers or subclasses of <code>Category</code> need supply their |
| fully qualified class name to the <code>Category.log</code> method or |
| to <code>Category.forcedLog</code> methods so that the caller location |
| information can be extracted correctly.</p> |
| |
| <p>This approach will work correctly in all cases except if |
| the class invoking the extended category instance has the |
| same prefix as the extended category class. For example, |
| calling an instance of <code>com.foo.BarCategory</code> |
| from the <code>com.foo.BarCategoryTest</code> class will |
| not yield the correct caller information. To circumvent |
| this "bug", either perform the tests from a class with a |
| different name or add a dot to the fully qualified name of |
| the extending class that you supply to |
| <code>Category.log</code> to |
| <code>Category.forcedLog</code> methods. For the |
| <code>com.foo.BarCategory</code> example, supply the |
| string <code>"com.foo.BarCategory."</code>.</p> |
| |
| |
| <p><a name=cce><h3><code>ClassCastException</code> when |
| instantiating a <code>Category</code> subclasses.</a></h3> |
| |
| <p>This exception is thrown because log4j does not support |
| homonyms. For example, the following will systematically throw a |
| <code>ClassCastException</code></p> |
| |
| <pre> |
| Category c1 = Category.getInstance("bad"); |
| MyCategory c2 = (MyCategory) MyCategory.getInstance("bad"); |
| </pre> |
| |
| where <code>MyCategory</code> is a subclass of |
| <code>Category</code>. The problem occurs because the second |
| <code>getInstance</code> invocation will retrieve the category created |
| in the fist invocation. This instance is a <code>Category</code> |
| object and cannot be cast to <code>MyCategory</code>.</p> |
| |
| <p>By default, the <code>PropertyConfigurator</code> will |
| create and configure |
| <code>org.apache.log4j.Category</code> objects. Thus, if |
| you try to instantiate a category subclass for an already |
| existing category, and try to cast it to the subclass |
| type, you will systematically get a |
| <code>ClassCastException</code>.</p> |
| |
| <p>To address this problem, the |
| <code>PropertyConfigurator</code> admits the |
| <code>log4j.categoryFactory</code> key. The value of this |
| key will be used as the factory to invoke when |
| instantiating Category objects. |
| |
| <p>The <code>DOMConfigurator</code> has a finer grain |
| method for setting the class of the category object to instantiate. |
| |
| |
| <!-- <a name="#levelCast"><h3>Compilation errors when using <code>setLevel(org.apache.log4j.Level)</code> from the Category class.</h3> |
| |
| <p>If you try to call the setLevel method with one of the built in |
| levels, the java compiler with complain: |
| |
| <pre> |
| [javac] setLevel(org.apache.log4j.Level) in org.apache.log4j.Category cannot be applied to (org.apache.log4j.Priority) |
| [javac] logger.setLevel(Level.DEBUG); |
| </pre> |
| where logger is a variable of type Logger. |
| |
| <p>Casting any of the Level.DEBUG, Level.INFO, Level.WARN, |
| Level.ERROR, Level.FATAL arguments to Level will make the compiler |
| happy. As in <pre> logger.setLevel(<b>(Level)</b> Level.DEBUG); |
| </pre> |
| |
| <p>This cast is always safe because log4j 1.2 will never produce |
| anything but <code>Level</code> objects, never <code>Priority</code> |
| objects. Surprisingly enough this cast was not necessary in log4j 1.2 |
| alpha. It is required in 1.2 beta and later to ensure runtime |
| compatibility with log4j 1.1.3.</p> |
| |
| --> |
| |
| <p><a name=notfound><h3>Log4j class not found/defined</h3> |
| |
| <p>Naturally you should check the classpath. But you should also |
| be aware of the presence of multiple classloaders in the JVM: |
| <p> <ol> |
| <li>the bootstrap classloader |
| <li>the extension classloader |
| <li>the application classloader |
| </ol> |
| <p>If you place log4j.jar in the <code>jre/lib/ext</code> directory |
| but place user-defined extensions to log4j in the application |
| classloader classpath, log4j configurators will not find them. |
| |
| <p>Servlet, JSP and EJB containers inside of application servers |
| usually have their own special classloaders in addition to the |
| three mentioned above. While this provides for a greater |
| degree of separation for different webapps, EJB containers and the |
| application server runtime itself, it can provide headaches to the |
| uninitiated. |
| |
| <p>Classloaders are usually hierarchically related. The bootstrap |
| loader forms the root with the extension loader as its child. The |
| application loader is the child of the extension loader and it's |
| this "app loader" that we use by default when we write standalone |
| Java programs. |
| |
| <p>Upon receiving a class load request, the classloader usually |
| delegates it to the parent before attempting to service the request. |
| This allows the bootstrap and extension loaders to deliver any classes |
| that are part of the JDK or its extensions. Only after this delegation |
| fails will the classloader attempt to find the class itself. Note that |
| classloaders do not delegate requests to children. |
| |
| <p>Application servers often use the application loader for its runtime |
| classes and create separate classloaders for its webapp and EJB |
| containers. These additional classloaders may descend directly |
| from the app server's runtime classloader. If log4j is placed in the |
| classpath of a webapp classloader, another webapp classloader will not |
| necessarily see it. EJBs wouldn't see it either. If log4j is intended |
| to be made available to all objects participating in the app server, it |
| should be included in the classpath of a classloader high enough in the |
| classloader hierarchy to be seen by all classloaders. |
| |
| <p>A good article on classloaders with examples using IBM's WebSphere |
| application server can be found |
| <a href="http://www7.software.ibm.com/vadd-bin/ftpdl?1/vadc/wsdd/pdf/gisell/UnderstandingWebSphereClassLoaders.pdf">here</a> |
| in PDF format. |
| |
| <h3><p><a name="syslogd">I cannot log to syslogd under linux.</a></h3> |
| |
| If you are trying to log to the Unix syslog under Linux using the <a |
| href="api/org/apache/log4j/net/SyslogAppender.html">SyslogAppender</a>, |
| then the Linux syslog daemon must be configured to accept log input |
| from the network. Otherwise, you will get an <code>IOException: |
| connection refused</code>. |
| |
| <p>This can be done by adding the <code>-r</code> option when starting |
| the daemon. Or more precisely: |
| |
| <ol> |
| <li>Login as the <code>root</code> user |
| <li>Edit file <code>/etc/rc/init.d/syslog</code> |
| <pre> |
| case "$1" in |
| start) |
| echo -n "Starting system logger: " |
| daemon syslogd -r |
| </pre> |
| |
| <li><code>/etc/rc/init.d/syslog restart</code> |
| |
| </ol> |
| |
| <p><a name=#nosuchpropperty><h3>log4j:WARN No such property [xyz] in some.appender.or.layout</h3> |
| |
| <p>If during log4j configuration you get a warning about an inexistent |
| property, then you have probably misspelled a property or entered a |
| truly unrecognized property for the component you are trying to |
| configure in the configuration file. |
| |
| <p>Log4j version 1.0 did not complain about unrecognized properties |
| whereas log4j version 1.1 and later do complain. |
| |
| |
| |
| |
| </body> |
| </html> |