Author: rgoers
Date: Sun Feb 5 21:50:04 2012
New Revision: 1240834
URL: http://svn.apache.org/viewvc?rev=1240834&view=rev
Log:
Finish documenting the API
Added:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/eventlogging.xml
- copied, changed from r1236171,
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/flowtracing.xml
- copied, changed from r1236171,
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/markers.xml
- copied, changed from r1236171,
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/site.xml
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/messages.xml
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/thread-context.xml
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
Sun Feb 5 21:50:04 2012
@@ -64,6 +64,10 @@ public final class ExtendedThrowablePatt
}
ThrowableProxy t = (ThrowableProxy) throwable;
String trace = t.getExtendedStackTrace();
+ int len = toAppendTo.length();
+ if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len -
1))) {
+ toAppendTo.append(" ");
+ }
if (lines > 0) {
StringBuilder sb = new StringBuilder();
String[] array = trace.split("\n");
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
Sun Feb 5 21:50:04 2012
@@ -414,7 +414,7 @@ public final class PatternParser {
return null;
}
- Method[] methods = converterClass.getMethods();
+ Method[] methods = converterClass.getDeclaredMethods();
Method newInstance = null;
for (Method method : methods) {
if (method.getName().equals("newInstance")) {
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/RootThrowablePatternConverter.java
Sun Feb 5 21:50:04 2012
@@ -65,6 +65,10 @@ public final class RootThrowablePatternC
}
ThrowableProxy t = (ThrowableProxy) throwable;
String trace = t.getRootCauseStackTrace();
+ int len = toAppendTo.length();
+ if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len -
1))) {
+ toAppendTo.append(" ");
+ }
if (lines > 0) {
StringBuilder sb = new StringBuilder();
String[] array = trace.split("\n");
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
Sun Feb 5 21:50:04 2012
@@ -96,6 +96,10 @@ public class ThrowablePatternConverter e
if (t != null) {
StringWriter w = new StringWriter();
t.printStackTrace(new PrintWriter(w));
+ int len = toAppendTo.length();
+ if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len -
1))) {
+ toAppendTo.append(" ");
+ }
if (lines > 0) {
StringBuilder sb = new StringBuilder();
String[] array = w.toString().split("\n");
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/site.xml
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/site.xml?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
--- logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/site.xml
(original)
+++ logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/site.xml Sun
Feb 5 21:50:04 2012
@@ -48,8 +48,9 @@
<item name="Architecture" href="/manual/architecture.html"/>
<item name="API" href="/manual/api.html" collapse="true">
<item name="Overview" href="manual/api.html#Overview"/>
- <item name="Markers" href="manual/api.html#Markers"/>
- <item name="Event Logging" href="/manual/api.html#EventLogging"/>
+ <item name="Flow Tracing" href="manual/flowtracing.html"/>
+ <item name="Markers" href="manual/markers.html"/>
+ <item name="Event Logging" href="/manual/eventlogging.html"/>
<item name="Messages" href="/manual/messages.html"/>
<item name="ThreadContext" href="/manual/thread-context.html"/>
</item>
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
Sun Feb 5 21:50:04 2012
@@ -73,15 +73,6 @@
only occur when debug logging is enabled.
</p>
</subsection>
- <a name="Markers"/>
- <subsection name="Markers">
-
- </subsection>
- <a name="EventLogging"/>
- <subsection name="EventLogging">
-
- </subsection>
-
</section>
</body>
</document>
\ No newline at end of file
Copied:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/eventlogging.xml
(from r1236171,
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml)
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/eventlogging.xml?p2=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/eventlogging.xml&p1=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml&r1=1236171&r2=1240834&rev=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/eventlogging.xml
Sun Feb 5 21:50:04 2012
@@ -24,64 +24,118 @@
<body>
<section name="Log4j 2.0 API">
- <a name="Overview"/>
- <subsection name="Overview">
- <p>
- The Log4Jj 2.0 API provides the interface that applications
should code to and provides the
- adapter components required for implementers to create a logging
implementation. Although Log4j 2
- is broken up between an API and an implementation, the primary
purpose of doing so was not to
- allow multiple implementations, although that is certainly
possible, but to clearly define
- what classes and methods are safe to use in "normal" application
code.
- </p>
- <h4>Hello World!</h4>
+ <a name="EventLogging"/>
+ <subsection name="Event Logging">
<p>
- No introduction would be complete without the customary Hello,
World example. Here is ours. First,
- a Logger with the name "HelloWorld" is obtained from the
LogManager. Next, the logger is used to
- write the "Hello, World!" message, however the message will be
written only if the Logger is
- configured to allow informational messages.
- </p>
- <source> import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+ The EventLogger class provides a simple mechansim for logging
events that occur in an application.
+ While the EventLogger is useful as a way of initiating events
that should be processed by an audit
+ Logging system, by itself it does not implement any of the
features an audit logging system would require
+ such as guaranteed delivery.
+ </p>
+ <p>The recommended way of using the EventLogger in a typcial web
application is to populate
+ the ThreadContext Map with data that is related to the entire
lifespan of the request such as the user's
+ id, the user's ip address, the product name, etc. This can
easily be done in a servlet fileter where
+ the ThreadContext Map can also be cleared at the end of the
request. When an event that needs to be
+ recorded occurs a StructuredDataMessage should be created and
populated.
+ Then call EventLogger.logEvent(msg) where msg is a reference to
the StructuredDataMessage.</p>
+
+ <source> import org.apache.logging.log4j.ThreadContext;
+ import org.apache.commons.lang.time.DateUtils;
+
+ import javax.servlet.Filter;
+ import javax.servlet.FilterConfig;
+ import javax.servlet.ServletException;
+ import javax.servlet.ServletRequest;
+ import javax.servlet.ServletResponse;
+ import javax.servlet.FilterChain;
+ import javax.servlet.http.HttpSession;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.Cookie;
+ import javax.servlet.http.HttpServletResponse;
+ import java.io.IOException;
+ import java.util.TimeZone;
+
+ public class RequestFilter implements Filter {
+ private FilterConfig filterConfig;
+ private static String TZ_NAME = "timezoneOffset";
- public class HelloWorld {
- private static Logger logger = LogManager.getLogger("HelloWorld");
- public static void main(String[] args) {
- logger.info("Hello, World!");
+ public void init(FilterConfig filterConfig) throws ServletException {
+ this.filterConfig = filterConfig;
+ }
+
+ /**
+ * Sample filter that populates the MDC on every request.
+ */
+ public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest)servletRequest;
+ HttpServletResponse response =
(HttpServletResponse)servletResponse;
+ ThreadContext.put("ipAddress", request.getRemoteAddr());
+ HttpSession session = request.getSession(false);
+ TimeZone timeZone = null;
+ if (session != null) {
+ // Something should set this after authentication completes
+ String loginId = (String)session.getAttribute("LoginId");
+ if (loginId != null) {
+ ThreadContext.put("loginId", loginId);
+ }
+ // This assumes there is some javascript on the user's page to
create the cookie.
+ if (session.getAttribute(TZ_NAME) == null) {
+ if (request.getCookies() != null) {
+ for (Cookie cookie : request.getCookies()) {
+ if (TZ_NAME.equals(cookie.getName())) {
+ int tzOffsetMinutes =
Integer.parseInt(cookie.getValue());
+ timeZone = TimeZone.getTimeZone("GMT");
+ timeZone.setRawOffset((int)(tzOffsetMinutes *
DateUtils.MILLIS_PER_MINUTE));
+ request.getSession().setAttribute(TZ_NAME,
tzOffsetMinutes);
+ cookie.setMaxAge(0);
+ response.addCookie(cookie);
+ }
+ }
+ }
+ }
+ }
+ ThreadContext.put("hostname", servletRequest.getServerName());
+ ThreadContext.put("productName",
filterConfig.getInitParameter("ProductName"));
+ Threadcontext.put("locale",
servletRequest.getLocale().getDisplayName());
+ if (timeZone == null) {
+ timeZone = TimeZone.getDefault();
+ }
+ ThreadContext.put("timezone", timeZone.getDisplayName());
+ filterChain.doFilter(servletRequest, servletResponse);
+ ThreadContext.clear();
+ }
+
+ public void destroy() {
}
}</source>
- <p>
- The output from the call to logger.info() will vary
significantly depending on the configuration
- used. See the <a href="./configuration.html">Configuration</a>
section for more details.
- </p>
- <h4>Parameter Substitution</h4>
- <p>
- Frequently the purpose of logging is to provide information
about what is happening in the system,
- which requires including information about the objects being
manipulated. In Log4j 1.x this could
- be accomplished by doing:
- </p>
- <source> if (logger.isDebugEnabled()) {
- logger.debug("Logging in user " + user.getName() + " with id " +
user.getId());
- }</source>
- <p>
- Doing this repeatedly has the effect of making the code feel
like it is more about logging than the
- actual task at hand. In addition, it results in the logging
level being checked twice; once on the
- call to isDebugEnabled and once on the debug method. A better
alternative would be:
- </p>
- <source> logger.debug("Logging in user {} with id {}",
user.getName(), user.getId());</source>
- <p>
- With the code above the logging level will only be checked once
and the String construction will
- only occur when debug logging is enabled.
- </p>
- </subsection>
- <a name="Markers"/>
- <subsection name="Markers">
+ <p>Sample class that uses EventLogger.</p>
+ <source> import org.apache.logging.log4j.StructuredDataMessage;
+ import org.apache.logging.log4j.EventLogger;
- </subsection>
- <a name="EventLogging"/>
- <subsection name="EventLogging">
+ import java.util.Date;
+ import java.util.UUID;
- </subsection>
+ public class MyApp {
+ public String doFundsTransfer(Account toAccount, Account fromAccount,
long amount) {
+ toAccount.deposit(amount);
+ fromAccount.withdraw(amount);
+ String confirm = UUID.randomUUID().toString();
+ StructuredDataMessage msg = new StructureDataMessage(confirm,
null, "transfer");
+ msg.put("toAccount", toAccount);
+ msg.put("fromAccount", fromAccount);
+ msg.put("amount", amount);
+ EventLogger.logEvent(data);
+ return confirm;
+ }
+ }</source>
+ <p>The EventLogger class uses a Logger named "EventLogger".
EventLogger uses a logging level
+ of OFF as the default to indicate that it cannot be filtered.
These events can be
+ formatted for printing using the
+ <a
href="../log4j2-core/apidocs/org/apache/logging/log4j/core/layout/StructuredDataLayout.html">StructuredDataLayout</a>.
+ </p>
+ </subsection>
</section>
</body>
</document>
\ No newline at end of file
Copied:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/flowtracing.xml
(from r1236171,
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml)
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/flowtracing.xml?p2=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/flowtracing.xml&p1=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml&r1=1236171&r2=1240834&rev=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/flowtracing.xml
Sun Feb 5 21:50:04 2012
@@ -24,64 +24,219 @@
<body>
<section name="Log4j 2.0 API">
- <a name="Overview"/>
- <subsection name="Overview">
+ <a name="FlowTracing"/>
+ <subsection name="Flow Tracing">
<p>
- The Log4Jj 2.0 API provides the interface that applications
should code to and provides the
- adapter components required for implementers to create a logging
implementation. Although Log4j 2
- is broken up between an API and an implementation, the primary
purpose of doing so was not to
- allow multiple implementations, although that is certainly
possible, but to clearly define
- what classes and methods are safe to use in "normal" application
code.
- </p>
- <h4>Hello World!</h4>
- <p>
- No introduction would be complete without the customary Hello,
World example. Here is ours. First,
- a Logger with the name "HelloWorld" is obtained from the
LogManager. Next, the logger is used to
- write the "Hello, World!" message, however the message will be
written only if the Logger is
- configured to allow informational messages.
+ The Logger class provides logging methods that are quite useful
for following the
+ execution path of applications. These methods generate logging
events that can be filtered
+ separately from other debug logging. Liberal use of these
methods is encouraged as the output has
+ been found to
+ <ul>
+ <li>aid in problem diagnosis in development without requiring
a debug session</li>
+ <li>aid in problem diagnosis in production where no debugging
is possible</li>
+ <li>help educate new deveopers in learning the
application.</li>
+ </ul>
</p>
- <source> import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
-
- public class HelloWorld {
- private static Logger logger = LogManager.getLogger("HelloWorld");
- public static void main(String[] args) {
- logger.info("Hello, World!");
- }
- }</source>
<p>
- The output from the call to logger.info() will vary
significantly depending on the configuration
- used. See the <a href="./configuration.html">Configuration</a>
section for more details.
+ The two most used methods are the entry() and exit() methods.
entry() should be placed at the
+ beginning of methods, except perhaps ofr simple getters and
setters. entry() can be called
+ passing from 0 to 4 parameters. Typically these will be
parameters passed to the method.
+ The entry() method logs with a level of TRACE and uses a Marker
with a name of "ENTER" which
+ is also a "FLOW" Marker.
</p>
- <h4>Parameter Substitution</h4>
<p>
- Frequently the purpose of logging is to provide information
about what is happening in the system,
- which requires including information about the objects being
manipulated. In Log4j 1.x this could
- be accomplished by doing:
+ The exit() method should be placed before any return statement
or as the last statement of
+ methods without a return. exit() can be called with or without a
parameter. Typically, methods
+ that return void will use exit() while methods that return an
Object will use exit(Object obj).
+ The entry() method logs with a level of TRACE and uses a Marker
with a name of "EXIT" which is
+ also a "FLOW" Marker.
</p>
- <source> if (logger.isDebugEnabled()) {
- logger.debug("Logging in user " + user.getName() + " with id " +
user.getId());
- }</source>
<p>
- Doing this repeatedly has the effect of making the code feel
like it is more about logging than the
- actual task at hand. In addition, it results in the logging
level being checked twice; once on the
- call to isDebugEnabled and once on the debug method. A better
alternative would be:
+ The throwing() method can be used by an application when it is
throwing an exception that is
+ unlikely to be handled, such as a RuntimeExcpetion. This will
insure that proper diagnostics
+ are available if needed. The logging event generated will have a
level of ERROR and will have
+ an associated Marker with a name of "THROWING" which is also an
"EXCEPTION" Marker.
</p>
- <source> logger.debug("Logging in user {} with id {}",
user.getName(), user.getId());</source>
<p>
- With the code above the logging level will only be checked once
and the String construction will
- only occur when debug logging is enabled.
+ The catching() method can be used by an application when it
catches an Exception that it is not
+ going to rethrow, either explicitely or attached to another
Exception. The logging event generated
+ will have a level of ERROR and will have an associated Marker
with a name of "CATCHING" which is
+ also an "EXCEPTION" Marker.
</p>
- </subsection>
- <a name="Markers"/>
- <subsection name="Markers">
+ <p>
+ The following example shows a simple application using these
methods in a fairly typcial manner. The
+ throwing() is not present since no Exceptions are explicitely
thrown and not handled.
+ </p>
+ <source> package com.test;
- </subsection>
- <a name="EventLogging"/>
- <subsection name="EventLogging">
+ import org.apache.logging.log4j.Logger;
+ import org.apache.logging.log4j.LogManager;
- </subsection>
+ import java.util.Random;
+
+ public class TestService {
+ private Logger logger =
LogManager.getLogger(TestService.class.getName());
+
+ private String[] messages = new String[] {
+ "Hello, World",
+ "Goodbye Cruel World",
+ "You had me at hello"
+ };
+ private Random rand = new Random(1);
+
+ public String retrieveMessage() {
+ logger.entry();
+
+ String testMsg = getMessage(getKey());
+
+ return logger.exit(testMsg);
+ }
+ public void exampleException() {
+ logger.entry();
+ try {
+ String msg = messages[messages.length];
+ logger.error("An exception should have been thrown");
+ } catch (Exception ex) {
+ logger.catching(ex);
+ }
+ logger.exit();
+ }
+
+ public String getMessage(int key) {
+ logger.entry(key);
+
+ String value = messages[key];
+
+ return logger.exit(value);
+ }
+
+ private int getKey() {
+ logger.entry();
+ int key = rand.nextInt(messages.length);
+ return logger.exit(key);
+ }
+ }</source>
+ <p>
+ This test application uses the preceding service to generate
logging events.
+ </p>
+ <source> package com.test;
+
+ public class App {
+
+ public static void main( String[] args ) {
+ TestService service = new TestService();
+ service.retrieveMessage();
+ service.retrieveMessage();
+ service.exampleException();
+ }
+ }</source>
+ <p>
+ The configuration below will cause all output to be routed to
target/test.log. The pattern for
+ the FileAppender includes the class name, line number and method
name. Including these
+ in the pattern are critical for the log to be of value.
+ </p>
+ <source><![CDATA[ <?xml version="1.0" encoding="UTF-8"?>
+ <configuration status="error">
+ <appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M -
%msg%xEx%n"/>
+ </Console>
+ <File name="log" fileName="target/test.log" append="false">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M -
%msg%xEx%n"/>
+ </File>
+ </appenders>
+ <loggers>
+ <root level="trace">
+ <appender-ref ref="log"/>
+ </root>
+ </loggers>
+ </configuration>]]></source>
+ <p>
+ Here is the output that results from the Java classes and
configuration above.
+ </p>
+ <source>
+ 19:08:07.056 TRACE com.test.TestService 19 retrieveMessage - entry
+ 19:08:07.060 TRACE com.test.TestService 46 getKey - entry
+ 19:08:07.060 TRACE com.test.TestService 48 getKey - exit with (0)
+ 19:08:07.060 TRACE com.test.TestService 38 getMessage - entry parms(0)
+ 19:08:07.060 TRACE com.test.TestService 42 getMessage - exit with (Hello,
World)
+ 19:08:07.060 TRACE com.test.TestService 23 retrieveMessage - exit with
(Hello, World)
+ 19:08:07.061 TRACE com.test.TestService 19 retrieveMessage - entry
+ 19:08:07.061 TRACE com.test.TestService 46 getKey - entry
+ 19:08:07.061 TRACE com.test.TestService 48 getKey - exit with (1)
+ 19:08:07.061 TRACE com.test.TestService 38 getMessage - entry parms(1)
+ 19:08:07.061 TRACE com.test.TestService 42 getMessage - exit with
(Goodbye Cruel World)
+ 19:08:07.061 TRACE com.test.TestService 23 retrieveMessage - exit with
(Goodbye Cruel World)
+ 19:08:07.062 TRACE com.test.TestService 27 exampleException - entry
+ 19:08:07.077 DEBUG com.test.TestService 32 exampleException - catching
java.lang.ArrayIndexOutOfBoundsException: 3
+ at com.test.TestService.exampleException(TestService.java:29)
[classes/:?]
+ at com.test.App.main(App.java:9) [classes/:?]
+ at com.test.AppTest.testApp(AppTest.java:15) [test-classes/:?]
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
~[?:1.6.0_29]
+ at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
~[?:1.6.0_29]
+ at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
~[?:1.6.0_29]
+ at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
+ at
org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
[junit-4.3.1.jar:?]
+ at
org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35)
[surefire-junit4-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:115)
[surefire-junit4-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97)
[surefire-junit4-2.7.2.jar:2.7.2]
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
~[?:1.6.0_29]
+ at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
~[?:1.6.0_29]
+ at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
~[?:1.6.0_29]
+ at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
+ at
org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
[surefire-booter-2.7.2.jar:2.7.2]
+ at $Proxy0.invoke(Unknown Source) [?:?]
+ at
org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150)
[surefire-booter-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91)
[surefire-booter-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)
[surefire-booter-2.7.2.jar:2.7.2]
+ 19:08:07.087 TRACE com.test.TestService 34 exampleException -
exit</source>
+ <p>
+ Simply changing the root logger level to DEBUG in the example
above will reduce the output
+ considerably.
+ </p>
+ <source>
+ 19:13:24.963 DEBUG com.test.TestService 32 exampleException - catching
java.lang.ArrayIndexOutOfBoundsException: 3
+ at com.test.TestService.exampleException(TestService.java:29)
[classes/:?]
+ at com.test.App.main(App.java:9) [classes/:?]
+ at com.test.AppTest.testApp(AppTest.java:15) [test-classes/:?]
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
~[?:1.6.0_29]
+ at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
~[?:1.6.0_29]
+ at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
~[?:1.6.0_29]
+ at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
+ at
org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
[junit-4.3.1.jar:?]
+ at
org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
[junit-4.3.1.jar:?]
+ at
org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35)
[surefire-junit4-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:115)
[surefire-junit4-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97)
[surefire-junit4-2.7.2.jar:2.7.2]
+ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
~[?:1.6.0_29]
+ at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
~[?:1.6.0_29]
+ at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
~[?:1.6.0_29]
+ at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
+ at
org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
[surefire-booter-2.7.2.jar:2.7.2]
+ at $Proxy0.invoke(Unknown Source) [?:?]
+ at
org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150)
[surefire-booter-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91)
[surefire-booter-2.7.2.jar:2.7.2]
+ at
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)
[surefire-booter-2.7.2.jar:2.7.2]</source>
+ </subsection>
</section>
</body>
</document>
\ No newline at end of file
Copied:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/markers.xml
(from r1236171,
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml)
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/markers.xml?p2=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/markers.xml&p1=logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml&r1=1236171&r2=1240834&rev=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/api.xml
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/markers.xml
Sun Feb 5 21:50:04 2012
@@ -24,64 +24,74 @@
<body>
<section name="Log4j 2.0 API">
- <a name="Overview"/>
- <subsection name="Overview">
- <p>
- The Log4Jj 2.0 API provides the interface that applications
should code to and provides the
- adapter components required for implementers to create a logging
implementation. Although Log4j 2
- is broken up between an API and an implementation, the primary
purpose of doing so was not to
- allow multiple implementations, although that is certainly
possible, but to clearly define
- what classes and methods are safe to use in "normal" application
code.
- </p>
- <h4>Hello World!</h4>
+ <a name="Markers"/>
+ <subsection name="Markers">
<p>
- No introduction would be complete without the customary Hello,
World example. Here is ours. First,
- a Logger with the name "HelloWorld" is obtained from the
LogManager. Next, the logger is used to
- write the "Hello, World!" message, however the message will be
written only if the Logger is
- configured to allow informational messages.
- </p>
- <source> import org.apache.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
+ One of the primary purpose of a logging framework is to provide
the means to generate debugging and
+ diagnostic information only when it is needed, and to allow
filtering of that information so that it
+ does not overwhelm the system or the individuals who need to
make use of it. As an example, an
+ application desires to log its entry, exit and other operations
separately from SQL statements
+ being executed, and wishes to be able to log queries separate
from updates. One way to accomplish
+ this is shown below:
+ </p>
+ <source><![CDATA[ import org.apache.logging.log4j.Logger;
+ import org.apache.logging.log4j.LogManager;
+ import java.util.Map;
+
+ public class MyApp {
+
+ private Logger logger = LogManager.getLogger(MyApp.class.getName());
+ private static final Marker SQL_MARKER =
MarkerManager.getMarker("SQL");
+ private static final Marker UPDATE_MARKER =
MarkerManager.getMarker("SQL_UPDATE", SQL_MARKER);
+ private static final Marker QUERY_MARKER =
MarkerManager.getMarker("SQL_QUERY", SQL_MARKER);
- public class HelloWorld {
- private static Logger logger = LogManager.getLogger("HelloWorld");
- public static void main(String[] args) {
- logger.info("Hello, World!");
+ public String doQuery(String table) {
+ logger.entry(param);
+
+ logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);
+
+ return logger.exit();
}
- }</source>
- <p>
- The output from the call to logger.info() will vary
significantly depending on the configuration
- used. See the <a href="./configuration.html">Configuration</a>
section for more details.
- </p>
- <h4>Parameter Substitution</h4>
- <p>
- Frequently the purpose of logging is to provide information
about what is happening in the system,
- which requires including information about the objects being
manipulated. In Log4j 1.x this could
- be accomplished by doing:
- </p>
- <source> if (logger.isDebugEnabled()) {
- logger.debug("Logging in user " + user.getName() + " with id " +
user.getId());
- }</source>
+
+ public String doUpdate(String table, Map<String, String> params) {
+ logger.entry(param);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(UPDATE_MARKER, "UPDATE {} SET {}", table,
formatCols);
+
+ return logger.exit();
+ }
+
+ private String formatCols(Map<String, String> cols) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (Map.Entry<String, String> entry : cols.entrySet()) {
+ if (!first) {
+ sb.append(", ");
+ }
+ sb.append(entry.getKey()).append("=").append(entry.getValue());
+ first = false;
+ }
+ return sb.toString();
+ }
+ }]]></source>
<p>
- Doing this repeatedly has the effect of making the code feel
like it is more about logging than the
- actual task at hand. In addition, it results in the logging
level being checked twice; once on the
- call to isDebugEnabled and once on the debug method. A better
alternative would be:
+ In the example above it is now possible to add MarkerFilters to
only allow SQL update operations
+ to be logged, all SQL updates to be logged or to log everything
in MyApp.
</p>
- <source> logger.debug("Logging in user {} with id {}",
user.getName(), user.getId());</source>
<p>
- With the code above the logging level will only be checked once
and the String construction will
- only occur when debug logging is enabled.
+ Some important rules about Markers must be considered when using
them.
+ <ol>
+ <li>Markers must be unique. They are permanently registered by
name so care should be taken
+ to insure that Markers used in your application are distinct
from those in the application's
+ dependencies, unless that is what is desired.</li>
+ <li>Like many objects in Log4J2, Markers are immutable. If a
marker has a parent, the parent
+ must be named when the Marker is created and the parent
cannot be changed after creation.</li>
+ <li>Markers only have a single parent. Markers can, however,
have many children that reference
+ them.</li>
+ </ol>
</p>
</subsection>
- <a name="Markers"/>
- <subsection name="Markers">
-
- </subsection>
- <a name="EventLogging"/>
- <subsection name="EventLogging">
-
- </subsection>
-
</section>
</body>
</document>
\ No newline at end of file
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/messages.xml
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/messages.xml?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/messages.xml
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/messages.xml
Sun Feb 5 21:50:04 2012
@@ -23,9 +23,9 @@
</properties>
<body>
- <section name="Log4j 2.0 API Messages">
- <a name="Introduction"/>
- <subsection name="Introduction">
+ <section name="Log4j 2.0 API">
+ <a name="Messages"/>
+ <subsection name="Messages">
<p>
Although Log4j 2 provides Logger methods that accept Strings and
Objects, all of these are ulitmately
captured in Message objects that are then associated with the log
event. Applications are free to
@@ -66,10 +66,110 @@
are encountered. With Messages the Layout has the option of
delegating the formatting to the Message or
performing its formatting based on the type of Message encountered.
</p>
+ <p>
+ Borrowing from the earlier example illustrating Markers to identify
SQL statements being logged, Messages
+ can also be leveraged. First, the Message is defined.
+ </p>
+ <source><![CDATA[
- </subsection>
+ public class SQLMessage implements Message {
+ public enum SQLType {
+ UPDATE,
+ QUERY
+ };
+
+ prviate final SQLType type;
+ private final String table;
+ private final Map<String, String> cols;
+
+ public SQLMessage(SQLType type, String table) {
+ this(type, table, null);
+ }
+
+ public SQLMessage(SQLType type, String table, Map<String, String> cols) {
+ this.type = type;
+ this.table = table;
+ this.cols = cols;
+ }
+
+ public String getFormattedMessage() {
+ switch (type) {
+ case UPDATE:
+ return createUpdateString();
+ break;
+ case QUERY:
+ return createQueryString();
+ break;
+ default;
+ }
+ }
+
+ public String getMessageFormat() {
+ return type + " " + table;
+ }
+
+ public Object getParameters() {
+ return cols;
+ }
+
+ private String createUpdateString() {
+ }
+
+ private String createQueryString() {
+ }
+
+ private String formatCols(Map<String, String> cols) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (Map.Entry<String, String> entry : cols.entrySet()) {
+ if (!first) {
+ sb.append(", ");
+ }
+ sb.append(entry.getKey()).append("=").append(entry.getValue());
+ first = false;
+ }
+ return sb.toString();
+ }
+ }]]></source>
+ <p>
+ Next we can use the message in our application.
+ </p>
+ <source><![CDATA[ import org.apache.logging.log4j.Logger;
+ import org.apache.logging.log4j.LogManager;
+ import java.util.Map;
+
+ public class MyApp {
+
+ private Logger logger = LogManager.getLogger(MyApp.class.getName());
+ private static final Marker SQL_MARKER =
MarkerManager.getMarker("SQL");
+ private static final Marker UPDATE_MARKER =
MarkerManager.getMarker("SQL_UPDATE", SQL_MARKER);
+ private static final Marker QUERY_MARKER =
MarkerManager.getMarker("SQL_QUERY", SQL_MARKER);
+
+ public String doQuery(String table) {
+ logger.entry(param);
+
+ logger.debug(QUERY_MARKER, new
SQLMessage(SQLMessage.SQLType.QUERY, table);
+
+ return logger.exit();
+ }
+
+ public String doUpdate(String table, Map<String, String> params) {
+ logger.entry(param);
+
+ logger.debug(UPDATE_MARKER, new
SQLMessage(SQLMessage.SQLType.UPDATE, table, parmas);
+
+ return logger.exit();
+ }
+ }]]></source>
+ <p>
+ Notice that in contrast to the prior version of this example, the
logger.debug in doUpdate no longer
+ needs to be wrapped in an isDebugEnabled call as creation of the
SQLMessage is on the same order of
+ magnitude of performing that check. Furthermore, all the formatting
of the SQL columns is now hidden
+ in the SQLMessage instead of having to take place in the business
logic. Finally, if desired, Filters
+ and/or Layouts can be written to take special action when an
SQLMessage is encountered.
+ </p>
<a name="FormattedMessage"/>
- <subsection name="FormattedMessage">
+ <h4>FormattedMessage</h4>
<p>
A FormattedMessage will have setFormat and getFormat methods. The
setFormat method may be called by a
Layout to provide advice on how the Message should be formatted. If
the Message doesn't recognize the
@@ -77,9 +177,8 @@
StructuredDataMessage which accepts a format String of "XML" which
will cause it to format the event data
as XML instead of the RFC 5424 format.
</p>
- </subsection>
<a name="LocalizedMessage"/>
- <subsection name="LocalizedMessage">
+ <h4>LocalizedMessage</h4>
<p>
<a
href="../log4j2-api/apidocs/org/apache/logging/log4j/message/LocalizedMessage.html">LocalizedMessage</a>
is provided primarily to provide compatibility with Log4j 1.x.
Generally,
@@ -91,60 +190,52 @@
LocalizedMessage will attempt to locate a bundle with the name of
the Logger used to log the event. The
parameters to the Message will be incorporated into the Message
whereever the "{}" placeholders occur.
</p>
- </subsection>
<a name="LoggerNameAwareMessage"/>
- <subsection name="LoggerNameAwareMessage">
+ <h4>LoggerNameAwareMessage</h4>
<p>
LoggerNameAwareMessage is an interface with a setLoggerName method.
This method will be called during
event construction so that the Message has the name of the Logger
used to log the event when the
message is being formatted.
</p>
- </subsection>
<a name="MapMessage"/>
- <subsection name="MapMessage">
+ <h4>MapMessage</h4>
<p>
A MapMessage contains a Map of String keys and values. MapMessage
implements FormattedMessage and accepts
a format specifier of "XML", in which case the Map will be formatted
as XML. Otherwise, the Map will be
formatted as "key1=value1 key2=value2...".
</p>
- </subsection>
<a name="ObjectMessage"/>
- <subsection name="ObjectMessage">
+ <h4>ObjectMessage</h4>
<p>
Formats an Object by calling its toString method.
</p>
- </subsection>
<a name="ParameterizedMessage"/>
- <subsection name="ParameterizedMessage">
+ <h4>ParameterizedMessage</h4>
<p>
<a
href="../log4j2-api/apidocs/org/apache/logging/log4j/message/ParameterizedMessage.html">ParameterizedMessage</a>
handles messages that contain "{}" in the format to represent
replaceable tokens and the replacement
parameters.
</p>
- </subsection>
<a name="SimpleMessage"/>
- <subsection name="SimpleMessage">
+ <h4>SimpleMessage</h4>
<p>
SimpleMessage contains a String that requires no formatting.
</p>
- </subsection>
<a name="StructuredDataMessage"/>
- <subsection name="StructuredDataMessage">
+ <h4>StructuredDataMessage</h4>
<p>
<a
href="../log4j2-api/apidocs/org/apache/logging/log4j/message/StructuredDataMessage.html">StructuredDataMessage</a>
allows applications to add items to a Map as well as set the id to
allow a message to be formatted as a
Structured Data element in accordance with <a
href="http://tools.ietf.org/html/rfc5424">RFC 5424</a>.
</p>
- </subsection>
<a name="ThreadDumpMessage"/>
- <subsection name="ThreadDumpMessage">
+ <h4>ThreadDumpMessage</h4>
<p>
A ThreadDumpMessage, if logged, will generate stack traces for all
threads. If running on Java 6+ the
stack traces will include any locks that are held.
</p>
- </subsection>
<a name="TimestampMessage"/>
- <subsection name="TimestampMessage">
+ <h4>TimestampMessage</h4>
<p>
A TimestampMessage will provide a getTimestamp method that is called
during event construction. The
timestamp in the Message will be used in lieu of the current
timestamp.
Modified:
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/thread-context.xml
URL:
http://svn.apache.org/viewvc/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/thread-context.xml?rev=1240834&r1=1240833&r2=1240834&view=diff
==============================================================================
---
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/thread-context.xml
(original)
+++
logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers/src/site/xdoc/manual/thread-context.xml
Sun Feb 5 21:50:04 2012
@@ -23,8 +23,9 @@
</properties>
<body>
- <section name="Thread Context">
- <subsection name="Introduction">
+ <section name="Log4j 2.0 API">
+ <subsection name="Thread Context">
+ <h4>Introduction</h4>
<p>Log4j introduced the concept of the Mapped Diagnostic Context or
MDC. It has been documented and
discussed in numerous places including
<a
href="http://veerasundar.com/blog/2009/10/log4j-mdc-mapped-diagnostic-context-what-and-why/">Log4j
MDC: What and Why</a> and
@@ -40,8 +41,7 @@
NDC. Although these are frequently used for purposes other than
diagnosing problems, they are still
frequently referred to as the MDC and NDC in Log4j 2 since they
are already well known by those acronyms.
</p>
- </subsection>
- <subsection name="Fish Tagging">
+ <h4>Fish Tagging</h4>
<p>Most real-world systems have to deal with multiple clients
simultaneously. In a typical multithreaded
implementation of such asystem, different threads will handle
different clients. Logging is
especially well suited to trace and debug complex distributed
applications. A common approach to
@@ -109,8 +109,7 @@
<a
href="../log4j2-api/apidocs/org/apache/logging/log4j/ThreadContext.html">ThreadContext</a>
class are static.
</p>
- </subsection>
- <subsection name="Including the ThreadContext when writing logs">
+ <h4>Including the ThreadContext when writing logs</h4>
<p>
The PatternLayout provides mechanisms to print the contents of the
ThreadContext Map and Stack. Using
%X by itself will cause the full contents of the Map to be
included while %X{key} will cause the value