The version of Apache log4j used by SoundHelix.

[[ 🗃 ^aEp6o apache-log4j ]] :: [📥 Inbox] [📤 Outbox] [🐤 Followers] [🤝 Collaborators] [🛠 Commits]

Clone

HTTPS: git clone https://vervis.peers.community/repos/aEp6o

SSH: git clone USERNAME@vervis.peers.community:aEp6o

Branches

Tags

1.3alpha-7 :: src / xdocs /

faq.xml

<?xml version="1.0" encoding="iso-8859-1"?>



<document>



  <properties>

    <author email="not@disclosed">Ceki G�lc�</author>

    <title>Frequently Asked Questions about log4j</title>

  </properties>



<body>



  <center>

    <h2>Frequently Asked Questions about log4j</h2>

    <h3>Ceki  G&#252;lc&#252;, Paul Smith, Chris Taylor<br/>

    May 2002, last updated on September 15th, 2004</h3>

  </center>



   <faqSection>

    <title>Generalities</title>



    <text>

      <p>This section contains general questions about log4j.</p>

    </text>



    <question>

      <title>What is log4j?</title>

      <answer>

	<p>log4j is a tool to help the programmer output log statements to a

	variety of output targets.

	</p>



	<p>In case of problems with an application, it is helpful to

	enable logging so that the problem can be located. With log4j

	it is possible to enable logging at runtime without modifying

	the application binary.  The log4j package is designed so that

	log statements can remain in <i>shipped</i> code without

	incurring a high performance cost. It follows that the speed

	of logging (or rather not logging) is capital.

	</p>



	<p>At the same time, log output can be so voluminous that it quickly

	becomes overwhelming. One of the distinctive features of log4j is the

	notion of <i>hierarchical loggers</i>. Using loggers it is

	possible to selectively control which log statements are output at

	arbitrary  granularity.

	</p>



	<p>log4j is designed with two three goals in mind:

	reliability, speed and flexibility. There is a tight balance

	between these requirements. We believe that log4j strikes the

	right balance.

	</p>

      </answer>



    </question>

    



    <question>

      <title>Is log4j a reliable logging system?</title>

      <answer>

	<p>No. log4j is not reliable. It is a best-effort 

	<em>fail-stop</em> logging system.

	</p>



	<p>By fail-stop, we mean that log4j will not throw unexpected

	exceptions at run-time potentially causing your application to

	crash. <b>If for any reason, log4j throws an uncaught exception,

	please send an email to the <a

	href="mailto:log4j-user@logging.apache.org">log4j-user@logging.apache.org</a>

	mailing list</b>. Uncaught exceptions are handled as serious bugs

	requiring immediate attention.

	</p>



	<p>Moreover, log4j will not revert to System.out or System.err

	when its designated output stream is not opened, is not writable or

	becomes full. This avoids corrupting an otherwise working program by

	flooding the user's terminal because logging fails. However, log4j

	will output a single message to System.err indicating that logging can

	not be performed.

	</p>

      </answer>

    </question>



    <question>

      <title>What are the prerequisites for log4j?</title>

      <answer>

	<ul>

	  <li><p>Log4j versions upto and including 1.2.8 are

	  compatible with JDK 1.1.x and later.  Log4j version 1.3 will

	  be compatilble with JDK 1.2 and later.

	  </p></li>



	  <li><p>The DOMConfigurator is based on the DOM Level 1

	  API. The DOMConfigurator.configure(Element) method will work

	  with any XML parser that will pass it a DOM tree.

	  </p>

	  <p>The DOMConfigurator.configure(String filename) method and its

	  variants require a JAXP compatible XML parser, for example <a

	  href="http://xml.apache.org/">Xerces</a> or Sun's

	  parser. Compiling the DOMConfigurator requires the presence of a

	  JAXP parser in the classpath.

	  </p>

	  </li>



	  <li><p>The <code>org.apache.log4j.net.SMTPAppender</code>

	  relies on the <a

	  href="http://java.sun.com/products/javamail/">JavaMail

	  API</a>. It has been tested with JavaMail API version

	  1.2. The JavaMail API requires the <a

	  href="http://java.sun.com/beans/glasgow/jaf.html">JavaBeans

	  Activation Framework</a> package.

	  </p></li>



	  <li><p>The <code>org.apache.log4j.net.JMSAppender</code>

	  requires the presence of the JMS API as well as JNDI.

	  </p></li>



	  <li><p>log4j test code relies on the <a

	  href="http://www.junit.org">JUnit</a> testing framework.

	  </p></li>

	</ul>    	

      </answer>

    </question>



    <question>

      <title>What are the features of log4j?</title>

      <answer>

	<ul>



	  <li><p>log4j is optimized for speed.</p></li>



	  <li><p>log4j is based on a named logger hierarchy.</p></li>

	  

	  <li><p>log4j is fail-stop. However, altough it certainly

	  strives to ensure delivery, log4j does not guarantee that

	  each log statement will be delivered to its destination.

	  </p></li>



	  <li><p>log4j is thread-safe.</p></li>



	  <li><p>log4j is not restricted to a predefined set of

	  facilities.</p></li>



	  <li><p>Logging behavior can be set at runtime using a

	  configuration file. Configuration files can be property

	  files or in XML format.  </p></li>



	  <li><p>log4j is designed to handle Java Exceptions from the

	  start.</p></li>

	  

	  <li><p>log4j can direct its output to a file, the console,

	  an <code>java.io.OutputStream</code>,

	  <code>java.io.Writer</code>, a remote server using TCP, a

	  remote Unix Syslog daemon, to a remote listener using JMS,

	  to the NT EventLog or even send e-mail.  </p></li>



	  <li><p>log4j uses 6 levels, namely TRACE, DEBUG, INFO, WARN,

	  ERROR and FATAL.  </p></li>



	  <li><p>The format of the log output can be easily changed by

	  extending the <code>Layout</code>

          class.  </p></li>



	  <li><p>The target of the log output as well as the writing

	  strategy can be altered by implementations of the

	  <code>Appender</code> interface.  </p></li>



	  <li><p>log4j supports multiple output appenders per logger.

	  </p></li>



	  <li><p>log4j supports internationalization.</p></li>

	</ul>

      </answer>

    </question>



    <question>

      <title>Is there example code for using log4j?</title>

      <answer>

	<p>See the <code>examples/</code> directory.</p>

      </answer>

    </question>



    <question>

      <title>What documentation should I read to learn more about

      log4j?</title>

      <answer>

	<p>Make sure to read the <a href="manual.html">short

	manual</a>. It is also recommended to you read <a

	href="https://www.qos.ch/shop/products/log4j/log4j-Manual.jsp">The complete

	log4j manual</a> which is much more detailed and up to

	date. Both documents were written by Ceki G&#252;lc&#252;.

	</p>

      </answer>

    </question>



    <question>

      <title>Is log4j thread-safe?</title>

      <answer>

	<p>Yes, log4j is thread-safe. Log4j components are designed to

	be used in heavily multithreaded systems.</p>

      </answer>

    </question>



    <question>

      <title>What does log output look like?</title>

      <answer>



	<p>The log output can be customized in many ways. Moreover,

	one can completely override the output format by implementing

	one's own Layout.

	</p>



	<p>Here is an example output using <em>PatternLayout</em> with

	the conversion pattern <b>"%r [%t] %-5p %c{2} %x - %m%n"</b>

	</p>



	<pre class="screen_output">

176 [main] INFO  examples.Sort - Populating an array of 2 elements in reverse order.

225 [main] INFO  examples.SortAlgo - Entered the sort method.

262 [main] DEBUG SortAlgo.OUTER i=1 - Outer loop.

276 [main] DEBUG SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0

290 [main] DEBUG SortAlgo.OUTER i=0 - Outer loop.

304 [main] INFO  SortAlgo.DUMP - Dump of interger array:

317 [main] INFO  SortAlgo.DUMP - Element [0] = 0

331 [main] INFO  SortAlgo.DUMP - Element [1] = 1

343 [main] INFO  examples.Sort - The next log statement should be an error message.

346 [main] ERROR SortAlgo.DUMP - Tried to dump an uninitialized array.

        at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)

        at org.log4j.examples.Sort.main(Sort.java:64)

467 [main] INFO  examples.Sort - Exiting main method.

	</pre>



	<p>The first field is the number of milliseconds elapsed since

	the start of the program. The second field is the thread

	outputting the log statement. The third field is the level of

	the log statement. The fourth field is the rightmost two

	components of the logger making the log request. The fifth

	field (just before the '-') is the <em>nested diagnostic

	context</em> (NDC). Note the nested diagnostic context may be

	empty as in the first two statements. The text after the '-'

	is the message of the statement.

	</p>

      </answer>

    </question>





    <question>

      

      <title>Why should I use log4j when JDK 1.4 already ships with a

      logging API?</title>



      <answer>

        <p>

        Although both APIs are conceptually similar, the log4j API is

        significantly more flexible and offers many more features, too

        numerous to be listed here. You will discover that the

        additional features and flexibility turn out to be

        indispensable in the context of a mission-critical

        application.

        </p>



        <p>The open and collaborative way in which log4j is developped

        ensures that it continues to preserve and even widen its

        competitive edge. At some point, input from bright developpers

        from all over the world is bound to make a difference.

        </p>

      </answer>

    </question>



  </faqSection>



  <faqSection>

      <title>Using log4j</title>



    <text>

      <p>This section contains answers to questions encountered while

      using log4j.</p>

    </text>



    <question>

      <title>What are <em>Loggers</em>?</title>

      <answer>

	<p>Lggers lie at the heart of log4j. Loggers define a hierarchy and give

	the programmer <em>run-time</em> control on which statements are

	printed or not.

	</p>

	

	<p>Loggers are assigned levels. A log statement is printed

	depending on its level <em>and</em> its logger.

	</p>

	

	<p>Make sure to read the <a href="manual.html">log4j manual</a>

	for more information.

	</p>	

      </answer>

    </question>



    <question>

      <title>How can I change log behavior at runtime?</title>

      <answer>

	<p>Log behavior can be set using configuration files which are parsed

	at runtime. Using configuration files the programmer can define

	loggers and set their levels.

	</p>

	

	<p>The <code>PropertyConfigurator</code> defines a particular format

	of a configuration file. See also the <code>examples/Sort.java</code>

	example and associated configuration files.

	</p>

	

	<p>Configuration files can be specified in XML. See

	<code>log4j.dtd</code> and

	<code>org.log4j.xml.DOMConfigurator</code> for more details.

	</p>

	

	<p>See the various Layout and Appender components for specific

	configuration options.

	</p>

	

	<p>In addition to configuration files, the user may disable all

	messages belonging to a set of levels. See next item.

	</p>

      </answer>

    </question>



    <question>

      <title>What is the fastest way of (not) logging?</title>

      <answer>



	<p> For some logger <code>l</code>, writing, 

	</p>

	

	<pre class="source">

 l.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));

	</pre>

	

	<p>incurs the cost of constructing the message parameter, that is

	converting both integer <code>i</code> and <code>entry[i]</code> to a

	String, and concatenating intermediate strings. This, regardless of

	whether the message will be logged or not.

	</p>



	<p>If you are worried about speed, then write</p>

	<pre class="source">

   if(l.isDebugEnabled()) {

     l.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));

   }

	</pre>



	<p>This way you will not incur the cost of parameter

	construction if debugging is disabled for logger

	<code>l</code>. On the other hand, if the logger is debug

	enabled, you will incur the cost of evaluating whether the

	logger is enabled or not, twice: once in

	<code>debugEnabled</code> and once in <code>debug</code>.

	This is an insignificant overhead since evaluating a logger

	takes less than 1% of the time it takes to actually log a

	statement.

	</p>

	

        <h3>Better alternative based on message patterns</h3>

        <p>As of log4j version 1.3, there exists a significantly more

        convenient alternative based on message patterns. Assuming

        <code>entry</code> is an object, you can write:

        </p>



	<p class="source">

          l.debug("The new entry is {}.", entry);

	</p>



        <p>After evaluting whether to log or not, and only if the

        decision is positive, will the logger instace format the

        message and replace the '{}' pair with the string value of

        <code>entry</code>. In other words, the paramerized form does

        not incur the cost of parameter construction in case the log

        statement is disabled.

        </p>

        

        <p>Thus, the following two lines will yield the exact same

        output. However, the second form will perform at least 30

        (thirty) times faster in case of a <em>disabled</em> logging

        statement.

        </p>

        

	<p class="source">

          l.debug("The new entry is "+entry+"."); <br/>

          l.debug("The new entry is {}.", entry);

	</p>

        

        <p>A two argument variant is also availalble. For example, you

        can write:

        </p>

	<p class="source">

          l.debug("The new entry is {}. It replaces {}.", entry, oldEntry);

	</p>

        

     



      </answer>

    </question>



    <question>

      <title> Are there any suggested ways for naming loggers?</title>

      <answer>

	



	<p>Yes, there are.</p>



	<p>You can name loggers by <strong>locality</strong>. It turns out

	that instantiating a logger in each class, with the logger name

	equal to the fully-qualified name of the class, is a useful and

	straightforward approach of defining loggers. This approach has

	many benefits:

	</p>

	

	<ul>

	  <li>It is very simple to implement.</li>

	  

	  <li>It is very simple to explain to new developers.</li>

	  

	  <li>It automatically mirrors your application's own modular design.

	  </li>

	  <li>It can be further refined at will.</li>

	  

	  <li>Printing the logger automatically gives information on the locality

	  of the log statement.	  </li>

	</ul>



	<p>However, this is not the only way for naming loggers. A

	common alternative is to name loggers by <strong>functional

	areas</strong>. For example, the "database" logger, "RMI"

	logger, "security" logger, or the "XML" logger.

	</p>



	<p>You may choose to name loggers by functionality and

	subcategorize by locality, as in "DATABASE.com.foo.some.package.someClass" or

	"DATABASE.com.foo.some.other.package.someOtherClass".

	</p>

	

	<p><em>You are totally free in choosing the names of your

	loggers.</em> The log4j package merely allows you to manage your

	names in a hierarchy.  However, it is your responsibility to define

	this hierarchy.

	</p>

	

	<p>Note by naming loggers by locality one tends to name things by

	functionality, since in most cases the locality relates closely to

	functionality. 

	</p>



      </answer>

    </question>





    <question>

      <title>How do I get the fully-qualified name of a class in a static block?</title>

      <answer>

	<p>You can easily retrieve the fully-qualified name of a class in a

	static block for class X, with the statement

	<code>X.class.getName()</code>. Note that <code>X</code> is the class

	name and not an instance.  The <code>X.class</code> statement does

	<i>not</i> create a new instance of class <code>X</code>.

	</p>

	

	<p>Here is the suggested usage template:</p>



	<pre class="source">

package a.b.c;



public class Foo {

  final static Logger logger = Logger.getLogger(Foo.class);

  ... other code



}

	</pre>

      </answer>

    </question>



    <question>

      <title>Can the log output format be customized? </title>

      <answer>

	<p>Yes, you can extend the <code>Layout</code> class to create

	you own customized log format. Appenders can be parameterized

	to use the layout of your choice.

	</p>

      </answer>

    </question>

  





    <question>

      <title>What are the configurable options for <code>FooBarAppender</code>?</title>

      <answer>

	<p>Log4j uses JavaBeans style configuration.</p>



	<p>Thus, any setter method in <code>FooBarAppender</code>

	corresponds to a configurable option. For example, in <a

	href="api\org\apache\log4j\RollingFileAppender.html"><code>RollingFileAppender</code></a>

	the <a

	href="api/org/apache/log4j/RollingFileAppender.html#setMaxBackupIndex(int)"><code>setMaxBackupIndex(int

	maxBackups)</code></a> method corresponds to the

	<code>maxBackupIndex</code> option. The first letter of the

	option can be upper case, i.e.  <code>MaxBackupIndex</code>

	and <code>maxBackupIndex</code> are equivalent but not

	<code>MAXBACKUPIndex</code> nor <code>mAXBackupIndex</code>.

	</p>



	<p>Layouts options are also defined by their setter methods. The same goes

	for most other log4j components.

	</p>

      </answer>

    </question>





   <question>

      <title>What is the recommended way of migrating from

      java.util.logging to log4j?</title>

      <answer>

	

	<p>We suggest to just use global file search/replace.  You should be able

	to replace all the "java.util.Logger" references with

	"org.apache.log4j.Logger", and you should be on your way.

	</p>

	

	<p>If you're on a Win32 platform, we recommend <a

	href="http://www.textpad.com/">Textpad</a>. You can use the

	CTRL+SHIFT+O to open all *.java files from a directory including all

	its sub-directories, and then use the search/replace function to

	replace in all files, and then CTRL+SHIFT+S to save all.  Should take

	about 60 seconds!  :)

	</p>

      </answer>

    </question>





    <question>

      <title>Is it possible to direct log output to

      different appenders by level? </title>

      <answer>

	<p>Yes it is. Setting the <b>Threshold</b> option of any appender

	extending <a

	href="api/org/apache/log4j/AppenderSkeleton.html">AppenderSkeleton</a>,

	(most log4j appenders extend AppenderSkeleton) to filter out all log

	events with <em>lower</em> level than the value of the threshold

	option. 

	</p>



	<p>For example, setting the threshold of an appender to DEBUG

	also allow INFO, WARN, ERROR and FATAL messages to log along

	with DEBUG messages. This is usually acceptable as there is

	little use for DEBUG messages without the surrounding INFO,

	WARN, ERROR and FATAL messages. Similarly, setting the

	threshold of an appender to ERROR will filter out DEBUG, INFO

	and WARN messages but not ERROR or FATAL messages.

	</p>



	<p>This policy usually best encapsulates what the user

	actually wants to do, as opposed to her mind-projected

	solution.

	</p>

	<p>See <i>examples/sort4.lcf</i> for an example threshold

	configuration.</p>



	<p>If you must filter events by exact level match, then you can

	attach a <a

	href="api/org/apache/log4j/varia/LevelMatchFilter.html">LevelMatchFilter</a>

	to any appender to filter out logging events by exact level match.

	</p>



      </answer>

    </question>





    <question>

      <title>What does the Windows NT Event Viewer complain about

      missing descriptions for my event messages when I use the

      <code>NTEventLogAppender</code>?</title>

      

      <answer>

	<p>The NT Event Viewer relies on <i>message resource</i> DLLs

	to properly view an event message.  The NTEventLogAppender.dll

	contains these message resources, but that DLL must be copied

	to %SYSTEMROOT%\SYSTEM32 for it to work properly.

	</p>

      </answer>

    </question>





    <question>

      <title>Why can't I map my logger names to the loggers that

      appear in the NT Event Log when I use the

      NTEventLogAppender?</title>

      <answer>

																				

	<p>Unfotunately, the logger names are hardcoded within the

	message resource DLL (see previous question about

	NTEventLogAppender), so there isn't any easy way to override

	those dynamically... in fact, I don't think it's possible to

	do it, as you'd have to modify the DLL resources for every

	application. Since most native applications don't use the

	Logger column anyway...

	</p>

      </answer>

    </question>



    

    <question>

      <title>Are there suggested approaches for logging in JSP pages?</title>

      <answer>

        <p>

        The suggested approach depends on your design requirements.  If you or

        your organization has no constraints on the use of Java in JSP pages,

        simply use log4j normally in <code>&lt;% ... %&gt;</code> statements

        as indicated in the Short Manual and the rest of the documentation.

        </p>

        <p>

        However, if your design calls for a minimum amount of Java in your JSP

        pages, consider using the

        <a href="http://jakarta.apache.org/taglibs/doc/log-doc/intro.html">Log Taglib</a>

        from the Jakarta Taglibs project.  It provides logging JSP tags that invoke

        log4j.

        </p>

      </answer>

    </question>

  

  </faqSection>



  <faqSection>

    <title>Advanced questions</title>



    <text>

      <p>This section contains answers to more advanced questions about log4j.</p>

    </text>



    <question>

      <title>Can the outputs of multiple client request go to

      different log files?</title>

      <answer>

	

	<p>Many developers are confronted with the problem of

	distinguishing the log output originating from the same class

	but different client requests. They come up with ingenious

	mechanisms to fan out the log output to different files. In

	most cases, this is not the right approach.

	</p>



	<p>It is simpler to use a nested diagnostic context

	(NDC). Typically, one would <em>NDC.push()</em> client

	specific information, such as the client's hostname, ID or any

	other distinguishing information when starting to handle the

	client's request. Thereafter, log output will automatically

	include the nested diagnostic context so that you can

	distinguish logs from different client requests even if they

	are output to the same file.

	</p>



	<p>See the <code>NDC</code> and the <code>PatternLayout</code>

	classes for more information. The <code>NumberCruncher</code>

	example shows how the NDC can be used to distinguish the log

	output from multiple clients even if they share the same log

	file.

	</p>



	<p>For select applications, such as virtual hosting

	web-servers, the NDC solution is not sufficient. As of version

	0.9.0, log4j supports multiple hierarchy trees. Thus, it is

	possible to log to different targets from the same logger

	depending on the current context.

	</p>



      </answer>

    </question>





    <question>

      <title>Logger instances seem to be create only. Why isn't

      there a method to remove logger instances?</title>

      <answer>

	<p>It is quite nontrivial to define the semantics of a

	"removed" logger escecially if it is still referenced by the

	user. Future releases <em>may</em> include a remove method in

	the Logger class.</p>

      </answer>

    </question>



    <question>

      <title>How do I get multiple process to log to the same file?</title>

      <answer>

	<p>You may have each process log to a 

	<a href="api/org/apache/log4j/net/SocketAppender.html"><code>SocketAppender</code></a>.  

	The receiving 

	<a href="api/org/apache/log4j/net/SocketServer.html"><code>SocketServer</code></a>  

	(or 

	<a href="api/org/apache/log4j/net/SimpleSocketServer.html"><code>SimpleSocketServer</code></a>)

	can receive all the events and send them to a single

	log file.

	</p>

      </answer>

    </question>

 

    <question>

      <title>How about the timesamps of events generated by multiple

      processes across multiple hosts (possibly across multiple

      timezones)?

      </title>



      <answer>

	

	<p>The timestamp is created when the logging event is created.

	That is so say, when the <code>debug</code>,

	<code>info</code>, <code>warn</code>, <code>error</code> or

	<code>fatal</code> method is invoked.  Thus, the timestamp is

	unaffected by the time at which event arrive at a remote

	socket server.  

	</p>

	

	<p>Timestamps are stored in UTC format inside the

	event. Consequently, when displayed or written to a log file,

	timestamps appear in the same timezone as the host displaying

	or creating the logfile.  Note that because the clocks of

	various machines may not be synchronized, there may be

	timestamp inconsistencies between events generated on

	different hosts.

	</p>

      </answer>

    </question>



    <question>

      <title>Why can't log4j find my properties file in a J2EE or WAR

      application?</title>



      <answer>



	<p>The short answer: the log4j classes and the properties file

	are not within the scope of the same classloader.

	</p>



	<p>The long answer (and what to do about it): J2EE or Servlet

	containers utilize Java's class loading system.  Sun changed

	the way classloading works with the release of Java 2.  In

	Java 2, classloaders are arranged in a hierarchial

	parent-child relationship.  When a child classloader needs to

	find a class or a resource, it first delegates the request to

	the parent.

	</p>



	<p>Log4j only uses the default <code>Class.forName()</code>

	mechanism for loading classes.  Resources are handled

	similarly.  See the documentation for

	<code>java.lang.ClassLoader</code> for more details.

	</p>



	<p>So, if you're having problems, try loading the class or

	resource yourself.  If you can't find it, neither will

	log4j. ;)

	</p>



      </answer>

    </question>



   <question>

      <title>Is there a way to get log4j to automatically reload a

      configuration file if it changes?</title>

      <answer>

	<p>Yes.  Both the DOMConfigurator and the PropertyConfigurator support

	automatic reloading through the <code>configureAndWatch</code> method.

	See the API documentation for more details.

	</p>





	<p>Because the <code>configureAndWatch</code> launches a

	separate wathdog thread, and because there is no way to stop

	this thread in log4j 1.2, the <code>configureAndWatch</code>

	method is unsafe for use in J2EE envrironments where

	applications are recycled.

	</p>

	

      </answer>

   </question>

  </faqSection>





  <faqSection>

    <title>Contributing to the project</title>

    <text>

      <p>This section includes questions about contributing to the

      project</p>

    </text>

    

    <question>

      <title>Why should I donate my extensions to log4j back to the

      project?

      </title>



      <answer>

	<p>Contrary to the GNU Public License (GPL) the Apache

	Software License does not make any claims over your

	extensions. By extensions, we mean totally new code that

	invokes existing log4j classes. <em>You are free to do

	whatever you wish with your proprietary log4j extensions.</em>

	In particular, you may choose to never release your extensions

	to the wider public.

	</p>

	

	<p>We are very careful not to change the log4j client API so

	that newer log4j releases are backward compatible with

	previous versions. We are a lot less scrupulous with the

	internal log4j API. Thus, if your extension is designed to

	work with log4j version <code>n</code>, then when log4j

	release version <code>n+1</code> comes out, you will probably

	need to adapt your proprietary extensions to the new release.

	</p>



	<p>Thus, you will be forced to spend precious resources in

	order to keep up with log4j changes. This is commonly referred

	to as the "stupid-tax."  By donating the code and making it

	part of the standard distribution, you save yourself the

	unnecessary maintenance work.

	</p>



	<p>If your extensions are useful then someone will eventually

	write an extension providing the same or very similar

	functionality.  Your development effort will be wasted. Unless

	the proprietary log4j extension is business critical, there is

	little reason for not donating your extensions back to the

	project.

	</p>

      </answer>

    </question>

    <question>

      <title>What should I keep in mind when contributing code?</title>

      <answer>

	<ol>



	  <li>

	    <p>Write a test case for your contribution.</p>



	    <p>There is nothing more irritating than finding the bugs

	    in debugging (i.e. logging) code. Writing a test case

	    takes some effort but is crucial for a widely used library

	    such as log4j. Writing a test case will go a long way in

	    earning you the respect of fellow developers. See the

	    tests/ directory for exiting test cases.

	    </p>

	  </li>



	  

	  <li>

	    <p>Stick to the existing indentation style even if you hate it.</p>

	    

	    <p>Alternating between indentation styles makes it hard to

	    understand the source code. Make it a little harder on

	    yourself but easier on others.

	    </p>



	    <p>Log4j has adopted a rather conservative approach by

	    following the <a

	    href="http://java.sun.com/docs/codeconv/">Code Conventions

	    for the JavaTM Programming Language</a>. <b>We use 2 (two)

	    spaces for indentation and no tabs.</b>

	    </p>

	  </li>



	  <li>

	    <p>Please do not both modify the code and change the

	    indentation in a single commit.</p>

	    

	    <p>If you change the code and reformat it at the same time

	    and then commit, the commit notification message will be

	    hard to read. It will contain many diffs associated with

	    the reformatting in addition to logical changes.

	    </p>



	    <p>If you must reformat and change the code, then perform

	    each step separately. For example, reformat the code and

	    commit. Following that, you can change the logic and

	    commit. The two steps can be performed in the reverse

	    order just as well. You can first change the logic and

	    commit and only later reformat and commit.

	    </p>



	  </li>

	  <li>

	    <p>Make every effort to stick to the JDK 1.1 API.</p>

	    

	    <p>One of the important advantages of log4j is its

	    compatibility with JDK 1.1.x.

	    </p>

	  </li>



	  <li>

	    <p>Always keep it simple, small and fast when

	    possible.</p>



	    <p>It's all about the application not about logging.</p>

	  </li>

	  

	  <li>

	    <p>Identify yourself as a contributor at the top of the

	    relevant file.

	    </p>

	  </li>

	  <li>

	    <p>Take responsibility for your code.</p>

	    

	    <p>Authoring software is very much like running a marathon. It

	    takes time and endurance.

	    </p>

	  </li>

	  <li>

	    <p>Did we mention sticking with the indentation style? </p>

	  </li>

	  <li><p>Did we mention writing test cases? </p>

	  </li>

	  

	</ol>

      </answer>

    </question>



    <question>

      <title>How can I contribute a new question/answer to this

      document?</title>

      <answer>

	<p>Log4j uses <a

	href="http://jakarta.apache.org/velocity/anakia.html">velocity-anakia</a>

	to generate its web-site, including this FAQ. We have devised

	special macros to help us automatically generate labeled

	question/answer pairs.

	</p>



	<p>If you are not a commiter, you can simply submit your new

	question/answer pair to the log4j-dev@logging.apache.org

	mailing list. The committers will take it from there.

	</p>



	<p>If you are a committer, then you must edit the

	<em>/src/xdocs/faq.xml</em> file. The format of the file

	should be self-evident. After you have made your changes, run

	the command

	</p>

	<pre class="source">ant site</pre>



	<p>After the appropriate transformation, your changes should

	appear in the file <em>/docs/faq.html</em>.

	</p>

      </answer>

    </question>

  </faqSection>

</body>

</document>










[See repo JSON]