This is an automated email from the ASF dual-hosted git repository. rgoers pushed a commit to annotated tag v1_2_1 in repository https://gitbox.apache.org/repos/asf/logging-log4j1.git
commit bcb0db698886247cbf3fd4c7a10bff72e1d2215a Author: No Author <[email protected]> AuthorDate: Fri May 17 12:48:49 2002 +0000 This commit was manufactured by cvs2svn to create tag 'v1_2_1'. git-svn-id: https://svn.apache.org/repos/asf/logging/log4j/tags/v1_2_1@309531 13f79535-47bb-0310-9956-ffa450edef68 --- BRANCHES | 61 ++++++++ INSTALL | 21 +-- build.xml | 4 +- docs/HISTORY | 13 +- docs/manual.html | 161 +++++++++++---------- src/java/org/apache/log4j/NDC.java | 3 +- src/java/org/apache/log4j/spi/LoggingEvent.java | 36 +++-- src/xdocs/documentation.xml | 4 - src/xdocs/download.xml | 22 ++- tests/build.xml | 2 +- tests/input/socketServer5.properties | 8 + .../org/apache/log4j/net/ShortSocketServer.java | 15 +- .../org/apache/log4j/net/SocketServerTestCase.java | 75 +++++++++- tests/witness/socketServer.5 | 35 +++++ 14 files changed, 331 insertions(+), 129 deletions(-) diff --git a/BRANCHES b/BRANCHES new file mode 100644 index 0000000..da0e39d --- /dev/null +++ b/BRANCHES @@ -0,0 +1,61 @@ + +Given that log4j 1.3 is not likely to be released before a few months, +I have created a branch called v1_2-branch in our CVS repository. The +branch was created by issuing the following command: + +cvs -d :ext:[email protected]:/home/cvs rtag -b -r v1_2final v1_2-branch jakarta-log4j + +Using the 1.2 branch, we can incorporate patches to log4j version 1.2 +while version 1.3 continues to be developed on the main trunk. For +example, we can officially release LogFactor5 (including +documentation) already in log4j 1.2.1. + +The command to access the v1_2-branch is: + +cvs -d XYZ checkout -r v1_2-branch jakarta-log4j + +where XYZ is the remote repository name, that is +":ext:[email protected]:/home/cvs" for me. + +Alternatively, you can issue following update command from within any +existing work copy. + + cvs update -r v1_2-branch + +Working with branches is not completely trivial and requires a little +coordination between committers, in particular in relation with branch +merge operations. In order to avoid multiple merge conflicts, each +time we merge from the 1.2 branch to the main trunk, we should tag the +merged version on the 1.2 branch. Subsequent merges should use the tag +referring to the latest merged version of the branch. Also do not +forget to publicly announce a merge operation. + +I am suggesting that (1.2 -> trunk) merge operations be done in a +concerted manner. Before doing a merge you tell everyone that you are +going to do a merge, you execute the merge operation, and then tag the +merged version on the 1.2 branch, for example v_1_2_-merged-bug666 + +The *next* merge operation would be performed as + + cvs update -j v_1_2_-merged-bug666 -j v1_2-branch + +from within a working copy of the *trunk*. This merge operation would +obviously also need to be tagged. According to the CVS manual, this +procedure eliminates the side effects of merging already merged +changes. + +Bug fixes should and documentation improvements, should be made to the +1.2 branch, not the trunk. I'll take care of merging the changes to +the main trunk. + +If this sounds like mambo jumbo, I urge you to consult the CVS +documentation and experiment with branches before hitting the log4j +repository. Branches are not that complicated really although they +require slightly more discipline on the part of committers. Do not +hesitate to shout if you need help. + +If you have a better alternative for working with branches please let +us know. + +-- +Ceki \ No newline at end of file diff --git a/INSTALL b/INSTALL index cf4fd20..d3db76b 100644 --- a/INSTALL +++ b/INSTALL @@ -11,7 +11,8 @@ Using log4j version number, under PATH_OF_YOUR_CHOICE. We will refer to the directory PATH_OF_YOUR_CHOICE/jakarta-log4j-VERSION/ as $LOG4J_HOME/. -3) Add $LOG4J_HOME/dist/lib/log4j-1.2.jar to your CLASSPATH. +3) Assuming you are using log4j version 1.2, add + $LOG4J_HOME/dist/lib/log4j-1.2.jar to your CLASSPATH, 4) You can now test your installation by first compiling the following simple program. @@ -57,8 +58,7 @@ except test cases and classes from the "examples" and log4j dependencies ================== -The log4j distribution comes with pre-compiled classes. Log4j is based -on JDK 1.1 with the following additional requirements: +Log4j is based on JDK 1.1 with the following additional requirements: ---------------------------- Package org.apache.log4j.xml @@ -82,7 +82,8 @@ on JDK 1.1 with the following additional requirements: The SMTPAppender relies on the JavaMail API. It has been tested with JavaMail API version 1.2. The JavaMail API requires the - JavaBeans Activation Framework package. You can download the JavaMail API at: + JavaBeans Activation Framework package. You can download the + JavaMail API at: http://java.sun.com/products/javamail/ @@ -104,8 +105,8 @@ on JDK 1.1 with the following additional requirements: ----------------------- Log4j uses the JUnit framework version 3.7 for internal unit - testing. If you want to compile all log4j source code, then you - will need JUnit. JUnit is available from: + testing. If you want to compile the source code in the tests/ + directory, then you will need JUnit. JUnit is available from: http://www.junit.org @@ -121,7 +122,7 @@ the build.properties and example of which is supplied in the build.properties.sample file. In case of problems send an e-mail note to [email protected]. Please do not directly e-mail any of -the log4j developers. The answer to your question might be useful to -other users. Moreover, there are many knowledgeable users on the -log4j-user mailing lists who can quickly answer your questions. [email protected]. Please do not directly e-mail any +log4j developers. The answer to your question might be useful to other +users. Moreover, there are many knowledgeable users on the log4j-user +mailing lists who can quickly answer your questions. diff --git a/build.xml b/build.xml index 9bcb740..4f2baaf 100644 --- a/build.xml +++ b/build.xml @@ -17,7 +17,7 @@ <!-- prefixed with "env". --> <property environment="env"/> - <property name="version" value="1.2"/> + <property name="version" value="1.2.1"/> <!-- The base directory relative to which most targets are built --> <property name="base" value="."/> @@ -413,6 +413,7 @@ examples/**, build/*, build.xml, + build.properties.sample, manifest.mf, INSTALL, LICENSE.txt, @@ -423,6 +424,7 @@ **/*.bak, **/goEnv.bat, **/Makefile, **/goEnv.bat, docs/pub-support/*, + dist/classes/org/**, src/java/org/apache/log4j/test/**/*, **/.#*"/> </copy> diff --git a/docs/HISTORY b/docs/HISTORY index d20fba1..f8974e3 100644 --- a/docs/HISTORY +++ b/docs/HISTORY @@ -5,7 +5,18 @@ client code. [***] Changes requiring important modifications to existing client code. - April, 2002 + May 17th, 2002 + + - Relase of version 1.2.1 + + - This minor release fixes bug #9155 reported by Nicko Cadell. + LoggingEvent.getMDCCopy() method now sets mdcCopyLookupRequired + instead of ndcLookupRequired. This bug would cause the wrong MDC + information to appear on a log server. It could only occur if the + client wrapped an AsyncAppender around a SocketAppender or if the + server used an AsyncAppender for its logging. [*] + + May, 2002 - Release of version 1.2 diff --git a/docs/manual.html b/docs/manual.html index 50c5331..2c24f45 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -90,7 +90,7 @@ book <i>"The Practice of Programming"</i> application. If too verbose, it can cause scrolling blindness. To alleviate these concerns, log4j is designed to be reliable, fast and extensible. Since logging is rarely the main focus of an application, -log4j API strives to be simple to understand and to use. +the log4j API strives to be simple to understand and to use. <h2>Loggers, Appenders and Layouts</h2> @@ -114,13 +114,13 @@ has replaced the <code>Category</code> class. For those familiar with earlier versions of log4j, the <code>Logger</code> class can be considered as a mere alias to the <code>Category</code> class. -<p> Loggers are named entities. Logger names are case-sensitive and +<p>Loggers are named entities. Logger names are case-sensitive and they follow the hierarchical naming rule: <p> <table bgcolor="#EEEE99"> <tr> - <td> + <td> <dl> <dt><b>Named Hierarchy</b> @@ -142,11 +142,11 @@ ancestor of <code>"java.util.Vector"</code>. This naming scheme should be familiar to most developers. <p>The root logger resides at the top of the logger hierarchy. It -is exceptional in two ways: +is exceptional in two ways: <ol> <li> it always exists, -<li> it cannot be retrieved by name. +<li> it cannot be retrieved by name. </ol> <p>Invoking the class static <a href="api/org/apache/log4j/Logger.html#getRootLogger()">Logger.getRootLogger</a> @@ -162,18 +162,19 @@ below. <td> <pre> package org.apache.log4j; - + public class <b>Logger</b> { - + // Creation & retrieval methods: public static Logger getRootLogger(); public static Logger getLogger(String name); - + // printing methods: public void debug(Object message); public void info(Object message); public void warn(Object message); public void error(Object message); + public void fatal(Object message); // generic printing method: public void log(Level l, Object message); @@ -183,19 +184,19 @@ below. </table> <p>Loggers <em>may</em> be assigned levels. The set of possible -levels, that is +levels, that is -<a href="api/org/apache/log4j/Level.html#DEBUG">DEBUG</a>, -<a href="api/org/apache/log4j/Level.html#INFO">INFO</a>, -<a href="api/org/apache/log4j/Level.html#WARN">WARN</a>, -<a href="api/org/apache/log4j/Level.html#ERROR">ERROR</a> and -<a href="api/org/apache/log4j/Level.html#FATAL">FATAL</a> +<a href="api/org/apache/log4j/Level.html#DEBUG">DEBUG</a>, +<a href="api/org/apache/log4j/Level.html#INFO">INFO</a>, +<a href="api/org/apache/log4j/Level.html#WARN">WARN</a>, +<a href="api/org/apache/log4j/Level.html#ERROR">ERROR</a> and +<a href="api/org/apache/log4j/Level.html#FATAL">FATAL</a> are defined in the <code><a href="api/org/apache/log4j/Level.html">org.apache.log4j.Level</a></code> -class. Although we do not encourage you from doing so, you may define +class. Although we do not encourage you to do so, you may define your own levels by sub-classing the <code>Level</code> class. A -perhaps better approach is will be explained later on. +perhaps better approach will be explained later on. <p>If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level. More @@ -205,7 +206,7 @@ formally: <p> <table bgcolor="#EEEE99"> <tr> - <td> + <td> <dl> <dt><b>Level Inheritance</b> @@ -231,10 +232,10 @@ resulting inherited levels according to the above rule. <tr align=left><td>X </td> <td>none</td> <td>Proot</td></tr> <tr align=left><td>X.Y </td> <td>none</td> <td>Proot</td></tr> <tr align=left><td>X.Y.Z</td> <td>none</td> <td>Proot</td></tr> - <caption align=bottom>Example 1</caption> + <caption align=bottom>Example 1</caption> </table> -<p>In example 1 above, only the root logger is assinged a +<p>In example 1 above, only the root logger is assigned a level. This level value, <code>Proot</code>, is inherited by the other loggers <code>X</code>, <code>X.Y</code> and <code>X.Y.Z</code>. @@ -288,17 +289,17 @@ having an assigned level.. <p>Logging requests are made by invoking one of the printing methods -of a logger instance. These printing methods are +of a logger instance. These printing methods are <code> <a href="api/org/apache/log4j/Logger.html#debug(java.lang.Object)">debug</a>, -<a href="api/org/apache/log4j/Logger.html#info(java.lang.Object)">info</a>, +<a href="api/org/apache/log4j/Logger.html#info(java.lang.Object)">info</a>, -<a href="api/org/apache/log4j/Logger.html#warn(java.lang.Object)">warn</a>, +<a href="api/org/apache/log4j/Logger.html#warn(java.lang.Object)">warn</a>, <a href="api/org/apache/log4j/Logger.html#error(java.lang.Object)">error</a>, <a href="api/org/apache/log4j/Logger.html#fatal(java.lang.Object)">fatal</a> - and <a href="api/org/apache/log4j/Logger.html#log(org.apache.log4j.Level, java.lang.Object)">log</a></code>. + and <a href="api/org/apache/log4j/Logger.html#log(org.apache.log4j.Level, java.lang.Object)">log</a></code>. <p>By definition, the printing method determines the level of a @@ -321,8 +322,8 @@ summarized below. <dt><b>Basic Selection Rule</b> <dd><p>A log request of level <i>p</i> in a logger with - inherited level <i>q</i>, is enabled if <i> p >= - q</i>. + (either assigned or inherited, whichever is appropriate) level <i>q</i>, is enabled if <i> p >= + q</i>. </dl> </table> @@ -330,7 +331,7 @@ summarized below. ordered. For the standard levels, we have <code>DEBUG < INFO < WARN < ERROR < FATAL</code>. -<p>Here is an example of this rule. +<p>Here is an example of this rule. <p><table bgcolor="CCCCCC"> <tr><td> @@ -339,35 +340,35 @@ ordered. For the standard levels, we have <code>DEBUG < INFO // get a logger instance named "com.foo" Logger logger = Logger.getLogger(<strong>"com.foo"</strong>); - // Now set its level. Normally you do not need to set the - // level of a logger progamitcally. This is usually done + // Now set its level. Normally you do not need to set the + // level of a logger programmatically. This is usually done // in configuration files. <strong>logger</strong>.setLevel(<font color="0000AA"><strong>Level.INFO</strong></font>); Logger barlogger = Logger.getLogger(<strong>"com.foo.Bar"</strong>); - + // This request is enabled, because <font color="00AA00"><strong>WARN</strong></font> >= <font color="0000AA"><strong>INFO</strong></font>. logger.<font color="00AA00"><strong>warn</strong></font>("Low fuel level."); - + // This request is disabled, because <font color="00AA00"><strong>DEBUG</strong></font> < <font color="0000AA"><strong>INFO</strong></font>. - logger.<font color="00AA00"><strong>debug</strong></font>("Starting search for nearest gas station."); - + logger.<font color="00AA00"><strong>debug</strong></font>("Starting search for nearest gas station."); + // The logger instance barlogger, named "com.foo.Bar", - // will inherit its level from the logger named - // "com.foo" Thus, the following request is enabled - // because <font color="00AA00"><strong>INFO</strong></font> >= <font color="0000AA"><strong>INFO</strong></font>. - barlogger.<font color="00AA00"><strong>info</strong></font>("Located nearest gas station."); + // will inherit its level from the logger named + // "com.foo" Thus, the following request is enabled + // because <font color="00AA00"><strong>INFO</strong></font> >= <font color="0000AA"><strong>INFO</strong></font>. + barlogger.<font color="00AA00"><strong>info</strong></font>("Located nearest gas station."); // This request is disabled, because <font color="00AA00"><strong>DEBUG</strong></font> < <font color="0000AA"><strong>INFO</strong></font>. - barlogger.<font color="00AA00"><strong>debug</strong></font>("Exiting gas station search"); + barlogger.<font color="00AA00"><strong>debug</strong></font>("Exiting gas station search"); </pre> -</table> +</table> <p>Calling the <code>getLogger</code> method with the same name will -always return a reference to the exact same logger object. +always return a reference to the exact same logger object. -<p>For example, in +<p>For example, in <table bgcolor="CCCCCC"> <tr><td> @@ -422,7 +423,7 @@ href="api/org/apache/log4j/net/JMSAppender.html">JMS</a>, Event Loggers</a>, and remote UNIX <a href="api/org/apache/log4j/net/SyslogAppender.html">Syslog</a> daemons. It is also possible to log <a href="api/org/apache/log4j/AsyncAppender.html">asynchronously</a>. - + <p>More than one appender can be attached to a logger. <p>The <a @@ -486,14 +487,14 @@ the additivity flag</a> to <code>false</code>. <tr><td>x.y <td>none <td>true <td>A1, A-x1, A-x2 <td>Appenders of "x" and root. -<tr><td>x.y.z <td>A-xyz1 <td>true <td>A1, A-x1, A-x2, A-xyz1 +<tr><td>x.y.z <td>A-xyz1 <td>true <td>A1, A-x1, A-x2, A-xyz1 <td>Appenders in "x.y.z", "x" and root. -<tr><td>security <td>A-sec <td><font color="blue">false</font> +<tr><td>security <td>A-sec <td><font color="blue">false</font> <td>A-sec <td>No appender accumulation since the additivity flag is set to - <code>false</code>. + <code>false</code>. <tr><td>security.access <td>none <td> true <td> A-sec <td>Only appenders of "security" because the additivity flag in "security" is @@ -507,7 +508,7 @@ destination but also the output format. This is accomplished by associating a <em>layout</em> with an appender. The layout is responsible for formatting the logging request according to the user's wishes, whereas an appender takes care of sending the formatted output -to its destination. +to its destination. The <a href="api/org/apache/log4j/PatternLayout.html">PatternLayout</a>, part @@ -533,7 +534,7 @@ message according to user specified criteria. For example, if you frequently need to log <code>Oranges</code>, an object type used in your current project, then you can register an <code>OrangeRenderer</code> that will be invoked whenever an orange -needs to be logged. +needs to be logged. <p>Object rendering follows the class hierarchy. For example, assuming oranges are fruits, if you register an <code>FruitRenderer</code>, all @@ -570,7 +571,7 @@ imaginary application <code>MyApp</code> that uses log4j. // Import log4j classes. <b>import org.apache.log4j.Logger; import org.apache.log4j.BasicConfigurator;</b> - + public class MyApp { // Define a static logger variable so that it references the @@ -585,7 +586,7 @@ imaginary application <code>MyApp</code> that uses log4j. logger.info("Entering application."); Bar bar = new Bar(); bar.doIt(); - logger.info("Exiting application."); + logger.info("Exiting application."); } } </pre> @@ -603,12 +604,12 @@ package <code>com.foo</code>. <pre> <b>package com.foo;</b> import org.apache.log4j.Logger; - + public class Bar { <strong>static</strong> Logger logger = <strong>Logger.getLogger(Bar.class);</strong> - + public void doIt() { - logger.debug("Did it again!"); + logger.debug("Did it again!"); } } </pre> @@ -624,7 +625,7 @@ href="api/org/apache/log4j/PatternLayout.html">PatternLayout</a> set to the pattern "%-4r [%t] %-5p %c %x - %m%n". <p>Note that by default, the root logger is assigned to -<code>Level.DEBUG</code>. +<code>Level.DEBUG</code>. <p>The output of MyApp is: <pre> @@ -635,7 +636,7 @@ to the pattern "%-4r [%t] %-5p %c %x - %m%n". <p>The figure below depicts the object diagram of <code>MyApp</code> after just having called the <code>BasicConfigurator.configure</code> -method. +method. <p> <center> @@ -658,7 +659,7 @@ retrieve the loggers they wish to use, and log away. <p>The previous example always outputs the same log information. Fortunately, it is easy to modify <code>MyApp</code> so that the log output can be controlled at run-time. Here is a slightly modified -version. +version. <p><table bgcolor="CCCCCC"><tr><td> <pre> @@ -666,21 +667,21 @@ version. import org.apache.log4j.Logger; <b>import org.apache.log4j.PropertyConfigurator;</b> - + public class MyApp { static Logger logger = Logger.getLogger(MyApp.class.getName()); public static void main(String[] args) { - + // BasicConfigurator replaced with PropertyConfigurator. <strong>PropertyConfigurator.configure(args[0]);</strong> logger.info("Entering application."); Bar bar = new Bar(); bar.doIt(); - logger.info("Exiting application."); + logger.info("Exiting application."); } } </pre> @@ -697,10 +698,10 @@ output as the previous <code>BasicConfigurator</code> based example. <pre> # Set root logger level to DEBUG and its only appender to A1. log4j.rootLogger=DEBUG, A1 - -# A1 is set to be a ConsoleAppender. + +# A1 is set to be a ConsoleAppender. log4j.appender.A1=org.apache.log4j.ConsoleAppender - + # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n @@ -721,10 +722,10 @@ configuration file shows one possible way of achieving this. log4j.rootLogger=DEBUG, A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout - + # <strong>Print the date in ISO 8601 format</strong> log4j.appender.A1.layout.ConversionPattern=<strong>%d</strong> [%t] %-5p %c - %m%n - + # Print only messages of level WARN or above in the package com.foo. <strong>log4j.logger.com.foo=WARN</strong> </pre> @@ -932,7 +933,7 @@ web-application. tells log4j to use the file <code>c:\foobar.lcf</code> as the default configuration file. The configuration file is fully specified by the URL <code>file:/c:/foobar.lcf</code>. Thus, the same configuration -file will be used for all web-applications. +file will be used for all web-applications. <p>Different web-applications will load the log4j classes through @@ -963,9 +964,9 @@ import java.io.PrintWriter; import java.io.IOException; public class Log4jInit extends HttpServlet { - + public - void <b>init()</b> { + void <b>init()</b> { String prefix = getServletContext().getRealPath("/"); String file = getInitParameter("log4j-init-file"); // if the log4j-init-file is not set, then no point in trying @@ -1029,19 +1030,19 @@ user pushes contextual information into the NDC, the abbreviation of <em>Nested Diagnostic Context</em>. The NDC class is shown below. <pre> - public class NDC { - // Used when printing the diagnostic - public <strong>static</strong> String get(); - + public class NDC { + // Used when printing the diagnostic + public <strong>static</strong> String get(); + // Remove the top of the context from the NDC. - public <strong>static</strong> String pop(); - + public <strong>static</strong> String pop(); + // Add diagnostic context for the current thread. - public <strong>static</strong> void push(String message); - - // Remove the diagnostic context for this thread. - public <strong>static</strong> void remove(); - } + public <strong>static</strong> void push(String message); + + // Remove the diagnostic context for this thread. + public <strong>static</strong> void remove(); + } </pre> <p>The NDC is managed per thread as a <em>stack</em> of contextual @@ -1096,7 +1097,7 @@ claims to be fast and flexible: speed first, flexibility second. machine this cost is typically in the 5 to 50 nanosecond range. <p>However, The method invocation involves the "hidden" cost of - parameter construction. + parameter construction. <p>For example, for some logger <code>cat</code>, writing, <pre> @@ -1113,12 +1114,12 @@ claims to be fast and flexible: speed first, flexibility second. <p>To avoid the parameter construction cost write: - <pre> + <pre> if(logger.isDebugEnabled() { logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); } </pre> - + <p>This will not incur the cost of parameter construction if debugging is disabled. On the other hand, if the logger is debug-enabled, it will incur twice the cost of @@ -1127,7 +1128,7 @@ claims to be fast and flexible: speed first, flexibility second. <code>debug</code>. This is an insignificant overhead because evaluating a logger takes about 1% of the time it takes to actually log. - + <p>In log4j, logging requests are made to instances of the Logger class. Logger is a class and not an interface. This measurably reduces the cost of method invocation at the cost of some diff --git a/src/java/org/apache/log4j/NDC.java b/src/java/org/apache/log4j/NDC.java index aa44615..b032744 100644 --- a/src/java/org/apache/log4j/NDC.java +++ b/src/java/org/apache/log4j/NDC.java @@ -192,7 +192,8 @@ public class NDC { /** - Used when printing the diagnostic context. + <font color="#FF4040"><b>Never use this method directly, use the {@link + org.apache.log4j.spi.LoggingEvent#getNDC} method instead.</b></font> */ static public diff --git a/src/java/org/apache/log4j/spi/LoggingEvent.java b/src/java/org/apache/log4j/spi/LoggingEvent.java index 5cd6e42..b35332c 100644 --- a/src/java/org/apache/log4j/spi/LoggingEvent.java +++ b/src/java/org/apache/log4j/spi/LoggingEvent.java @@ -62,18 +62,16 @@ public class LoggingEvent implements java.io.Serializable { /** Have we tried to do an NDC lookup? If we did, there is no need - to do it again. Note that its value is always false when - serialized. Thus, a receiving SocketNode will never use it's own - (incorrect) NDC. See also writeObject method. */ + * to do it again. Note that its value is always false when + * serialized. Thus, a receiving SocketNode will never use it's own + * (incorrect) NDC. See also writeObject method. */ private boolean ndcLookupRequired = true; - /** Have we tried to do an MDC lookup? If we did, there is no need to - do it again. Note that its value is always false when - serialized. Thus, a receiving SocketNode will never use it's own - (incorrect) MDC. See also writeObject method. */ - private boolean mdcLookupRequired = true; - + /** Have we tried to do an MDC lookup? If we did, there is no need + * to do it again. Note that its value is always false when + * serialized. See also the getMDC and getMDCCopy methods. */ + private boolean mdcCopyLookupRequired = true; /** The application supplied message of logging event. */ transient private Object message; @@ -187,6 +185,11 @@ public class LoggingEvent implements java.io.Serializable { } } + /** + * This method returns the NDC for this event. It will return the + * correct content even if the event was generated in a different + * thread or even on a different machine. The {@link NDC#get} method + * should <em>never</em> be called directly. */ public String getNDC() { if(ndcLookupRequired) { @@ -199,9 +202,11 @@ public class LoggingEvent implements java.io.Serializable { /** Returns the the context corresponding to the <code>key</code> - parameter. If there is a local MDC copy (probably from a remote - machine, the we use it, if that fails then the current thread's - <code>MDC</code> is used. + parameter. If there is a local MDC copy, possibly because we are + in a logging server or running inside AsyncAppender, then we + search for the key in MDC copy, if a value is found it is + returned. Otherwise, if the search in MDC copy returns a null + result, then the current thread's <code>MDC</code> is used. <p>Note that <em>both</em> the local MDC copy and the current thread's MDC are searched. @@ -223,11 +228,12 @@ public class LoggingEvent implements java.io.Serializable { /** Obtain a copy of this thread's MDC prior to serialization or - asynchronous logging. */ + asynchronous logging. + */ public void getMDCCopy() { - if(mdcLookupRequired) { - ndcLookupRequired = false; + if(mdcCopyLookupRequired) { + mdcCopyLookupRequired = false; // the clone call is required for asynchronous logging. // See also bug #5932. Hashtable t = (Hashtable) MDC.getContext(); diff --git a/src/xdocs/documentation.xml b/src/xdocs/documentation.xml index 0f2690a..ec3ea81 100644 --- a/src/xdocs/documentation.xml +++ b/src/xdocs/documentation.xml @@ -58,10 +58,6 @@ Add logging to your Java Applications</a> by Kevin Brown </li> - <li><a href="http://www.entwickler.com/jm/ausgaben/2001/4/artikel/17/online.shtml"> - Computer: captains, new entry... DasJakarta Logging-System log4j</a> by Thomas Poschmann - </li> - <li> <a href="http://www.opensymphony.com/guidelines/logging.jsp">OpenSymphony Logging Primer</a> </li> diff --git a/src/xdocs/download.xml b/src/xdocs/download.xml index 6f40fb1..4e8db25 100644 --- a/src/xdocs/download.xml +++ b/src/xdocs/download.xml @@ -9,13 +9,19 @@ <meta name="keywords" content="java, logging, tracing, component, framework, API, log4j"/> <body> - <section name="log4j version 1.2 (final)"> - <p>log4j 1.2 is now available in <a - href="../jakarta-log4j-1.2.tar.gz"><b>TAR.GZ</b></a> format or - in <a href="../jakarta-log4j-1.2.zip"><b>ZIP</b></a> format. + <section name="log4j version 1.2.1"> + <p>log4j 1.2.1 is now available in <a + href="../jakarta-log4j-1.2.1.tar.gz"><b>TAR.GZ</b></a> format + or in <a href="../jakarta-log4j-1.2.1.zip"><b>ZIP</b></a> + format. </p> - + <p>This minor release fixes bug #9155 reported by Nicko + Cadell. With the exception of this bug fix and some + documentation improvements, it is identical to log4j 1.2 + final. + </p> + <p>In addition to many performance improvements, bug fixes, and other small enhancements, log4j 1.2 adds JMX support, Mapped Diagnostic Contexts, JDBC logging, graphical log viewer @@ -57,9 +63,9 @@ <dt><a href="http://logui.sourceforge.net/"><b>Chainsaw</b></a></dt> - <dd>Chainsaw is now integrated with log4j and ships with the - official distribution. Chainsaw is a graphical log viewer and - filter for the log4j package. It listens for <a + <dd><b>Chainsaw is now integrated with log4j and ships with + the official distribution.</b> Chainsaw is a graphical log + viewer and filter for the log4j package. It listens for <a href="http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/spi/LoggingEvent.html">LoggingEvent</a> objects sent using the <a href="http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/net/SocketAppender.html">SocketAppender</a> diff --git a/tests/build.xml b/tests/build.xml index a249bdd..809c301 100644 --- a/tests/build.xml +++ b/tests/build.xml @@ -172,7 +172,7 @@ <target name="SocketServer" depends="build"> <parallel> <java classname="org.apache.log4j.net.ShortSocketServer" fork="yes"> - <arg value="4"/> + <arg value="5"/> <arg value="input/socketServer"/> <classpath refid="tests.classpath"/> </java> diff --git a/tests/input/socketServer5.properties b/tests/input/socketServer5.properties new file mode 100644 index 0000000..9772442 --- /dev/null +++ b/tests/input/socketServer5.properties @@ -0,0 +1,8 @@ +log4j.rootLogger=DEBUG, A +log4j.Logger.org.apache.log4j.test.ShortSocketServer=WARN +log4j.Logger.org.apache.log4j.net.SocketNode=WARN +log4j.appender.A=org.apache.log4j.FileAppender +log4j.appender.A.file=output/temp +log4j.appender.A.Append=false +log4j.appender.A.layout=org.apache.log4j.PatternLayout +log4j.appender.A.layout.ConversionPattern=%5p %x %X{key1}%X{key5} [%t] %c{1} - %m%n diff --git a/tests/src/java/org/apache/log4j/net/ShortSocketServer.java b/tests/src/java/org/apache/log4j/net/ShortSocketServer.java index 99b8d5c..4da0259 100644 --- a/tests/src/java/org/apache/log4j/net/ShortSocketServer.java +++ b/tests/src/java/org/apache/log4j/net/ShortSocketServer.java @@ -20,10 +20,15 @@ import org.apache.log4j.net.SocketNode; import org.apache.log4j.net.SocketServer; /** - This SocketServer exits after just one connection from a client. - - @author Ceki Gulcu -*/ + * This SocketServer exits after certain number of connections from a + * client. This number is determined the totalsTest parameter, that is + * the first argument on the commmand line. The second argument, + * prefix, determines the prefix of the configuration file to + * use. Each run of the server will use a different properties + * file. For the i-th run, the path to the file is + * (prefix+i+".properties"). + * + * @author Ceki Gulcu */ public class ShortSocketServer { @@ -61,7 +66,7 @@ public class ShortSocketServer { static - void usage(String msg) { + void usage(String msg) { System.err.println(msg); System.err.println( "Usage: java " +ShortSocketServer.class.getName() + " totalTests configFilePrefix"); diff --git a/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java b/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java index 3810ac2..defbbd4 100644 --- a/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java +++ b/tests/src/java/org/apache/log4j/net/SocketServerTestCase.java @@ -55,6 +55,9 @@ public class SocketServerTestCase extends TestCase { static String PAT4 = "^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some T4 MDC-TEST4 \\[main]\\" + " (root|SocketServerTestCase) - Message \\d{1,2}"; + static String PAT5 = "^(DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some5 T5 MDC-TEST5 \\[main]\\" + + " (root|SocketServerTestCase) - Message \\d{1,2}"; + static String EXCEPTION1 = "java.lang.Exception: Just testing"; static String EXCEPTION2 = "\\s*at .*\\(.*:\\d{1,4}\\)"; @@ -72,8 +75,6 @@ public class SocketServerTestCase extends TestCase { public void setUp() { System.out.println("Setting up test case."); - socketAppender = new SocketAppender("localhost", PORT); - rootLogger.addAppender(socketAppender); } public void tearDown() { @@ -81,8 +82,15 @@ public class SocketServerTestCase extends TestCase { socketAppender = null; rootLogger.removeAllAppenders(); } - + + /** + * The pattern on the server side: %5p %x [%t] %c %m%n + * + * We are testing NDC functionality across the wire. + */ public void test1() throws Exception { + socketAppender = new SocketAppender("localhost", PORT); + rootLogger.addAppender(socketAppender); common("T1", "key1", "MDC-TEST1"); delay(1); ControlFilter cf = new ControlFilter(new String[]{PAT1, EXCEPTION1, @@ -93,7 +101,16 @@ public class SocketServerTestCase extends TestCase { assertTrue(Compare.compare(FILTERED, "witness/socketServer.1")); } + /** + * The pattern on the server side: %5p %x [%t] %C (%F:%L) %m%n + * + * We are testing NDC across the wire. Localization is turned off by + * default so it is not tested here even if the conversion pattern + * uses localization. */ public void test2() throws Exception { + socketAppender = new SocketAppender("localhost", PORT); + rootLogger.addAppender(socketAppender); + common("T2", "key2", "MDC-TEST2"); delay(1); ControlFilter cf = new ControlFilter(new String[]{PAT2, EXCEPTION1, @@ -104,8 +121,15 @@ public class SocketServerTestCase extends TestCase { assertTrue(Compare.compare(FILTERED, "witness/socketServer.2")); } + /** + * The pattern on the server side: %5p %x [%t] %C (%F:%L) %m%n + * meaning that we are testing NDC and locatization functionality + * across the wire. */ public void test3() throws Exception { + socketAppender = new SocketAppender("localhost", PORT); socketAppender.setLocationInfo(true); + rootLogger.addAppender(socketAppender); + common("T3", "key3", "MDC-TEST3"); delay(1); ControlFilter cf = new ControlFilter(new String[]{PAT3, EXCEPTION1, @@ -116,10 +140,19 @@ public class SocketServerTestCase extends TestCase { assertTrue(Compare.compare(FILTERED, "witness/socketServer.3")); } + /** + * The pattern on the server side: %5p %x %X{key1}%X{key4} [%t] %c{1} - %m%n + * meaning that we are testing NDC, MDC and localization functionality across + * the wire. + */ public void test4() throws Exception { + socketAppender = new SocketAppender("localhost", PORT); socketAppender.setLocationInfo(true); + rootLogger.addAppender(socketAppender); + NDC.push("some"); common("T4", "key4", "MDC-TEST4"); + NDC.pop(); delay(1); ControlFilter cf = new ControlFilter(new String[]{PAT4, EXCEPTION1, EXCEPTION2, EXCEPTION3}); @@ -129,6 +162,41 @@ public class SocketServerTestCase extends TestCase { assertTrue(Compare.compare(FILTERED, "witness/socketServer.4")); } + /** + * The pattern on the server side: %5p %x %X{key1}%X{key5} [%t] %c{1} - %m%n + * + * The test case uses wraps an AsyncAppender around the + * SocketAppender. This tests was written specifically for bug + * report #9155. + + * Prior to the bug fix the output on the server did not contain the + * MDC-TEST5 string because the MDC clone operation (in getMDCCopy + * method) operation is performed twice, once from the main thread + * which is correct, and a second time from the AsyncAppender's + * dispatch thread which is incrorrect. + + */ + public void test5() throws Exception { + socketAppender = new SocketAppender("localhost", PORT); + socketAppender.setLocationInfo(true); + AsyncAppender asyncAppender = new AsyncAppender(); + asyncAppender.setLocationInfo(true); + asyncAppender.addAppender(socketAppender); + rootLogger.addAppender(asyncAppender); + + NDC.push("some5"); + common("T5", "key5", "MDC-TEST5"); + NDC.pop(); + delay(2); + ControlFilter cf = new ControlFilter(new String[]{PAT5, EXCEPTION1, + EXCEPTION2, EXCEPTION3}); + + Transformer.transform(TEMP, FILTERED, new Filter[] {cf, new LineNumberFilter()}); + + assertTrue(Compare.compare(FILTERED, "witness/socketServer.5")); + } + + static void common(String dc, String key, Object o) { int i = -1; @@ -161,6 +229,7 @@ public class SocketServerTestCase extends TestCase { suite.addTest(new SocketServerTestCase("test2")); suite.addTest(new SocketServerTestCase("test3")); suite.addTest(new SocketServerTestCase("test4")); + suite.addTest(new SocketServerTestCase("test5")); return suite; } } diff --git a/tests/witness/socketServer.5 b/tests/witness/socketServer.5 new file mode 100644 index 0000000..dec6b0e --- /dev/null +++ b/tests/witness/socketServer.5 @@ -0,0 +1,35 @@ +DEBUG some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 1 +DEBUG some5 T5 MDC-TEST5 [main] root - Message 2 + INFO some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 3 + WARN some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 4 +LETHAL some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 5 +DEBUG some5 T5 MDC-TEST5 [main] SocketServerTestCase - Message 6 +java.lang.Exception: Just testing + at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX) + at org.apache.log4j.net.SocketServerTestCase.test5(SocketServerTestCase.java:XXX) + at java.lang.reflect.Method.invoke(Native Method) + at junit.framework.TestCase.runTest(TestCase.java:XXX) + at junit.framework.TestCase.runBare(TestCase.java:XXX) + at junit.framework.TestResult$1.protect(TestResult.java:XXX) + at junit.framework.TestResult.runProtected(TestResult.java:XXX) + at junit.framework.TestResult.run(TestResult.java:XXX) + at junit.framework.TestCase.run(TestCase.java:XXX) + at junit.framework.TestSuite.runTest(TestSuite.java:XXX) + at junit.framework.TestSuite.run(TestSuite.java:XXX) + at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX) + at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX) +ERROR some5 T5 MDC-TEST5 [main] root - Message 7 +java.lang.Exception: Just testing + at org.apache.log4j.net.SocketServerTestCase.common(SocketServerTestCase.java:XXX) + at org.apache.log4j.net.SocketServerTestCase.test5(SocketServerTestCase.java:XXX) + at java.lang.reflect.Method.invoke(Native Method) + at junit.framework.TestCase.runTest(TestCase.java:XXX) + at junit.framework.TestCase.runBare(TestCase.java:XXX) + at junit.framework.TestResult$1.protect(TestResult.java:XXX) + at junit.framework.TestResult.runProtected(TestResult.java:XXX) + at junit.framework.TestResult.run(TestResult.java:XXX) + at junit.framework.TestCase.run(TestCase.java:XXX) + at junit.framework.TestSuite.runTest(TestSuite.java:XXX) + at junit.framework.TestSuite.run(TestSuite.java:XXX) + at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:XXX) + at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:XXX)
