You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2018/04/08 19:04:38 UTC

[1/5] logging-log4j2 git commit: LOG4J2-1802: Convert event logging manual page to asciidoc

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 59f34d768 -> 71b1f20f6


LOG4J2-1802: Convert event logging manual page to asciidoc


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/7c855d1e
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/7c855d1e
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/7c855d1e

Branch: refs/heads/master
Commit: 7c855d1e336b35f2a7735e2e2b2edf6fa903036a
Parents: 59f34d7
Author: Matt Sicker <bo...@gmail.com>
Authored: Sun Apr 8 13:44:29 2018 -0500
Committer: Matt Sicker <bo...@gmail.com>
Committed: Sun Apr 8 13:44:29 2018 -0500

----------------------------------------------------------------------
 src/site/asciidoc/manual/eventlogging.adoc | 142 +++++++++++++++++++++++
 src/site/xdoc/manual/eventlogging.xml      | 145 ------------------------
 2 files changed, 142 insertions(+), 145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7c855d1e/src/site/asciidoc/manual/eventlogging.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/manual/eventlogging.adoc b/src/site/asciidoc/manual/eventlogging.adoc
new file mode 100644
index 0000000..c91f1f7
--- /dev/null
+++ b/src/site/asciidoc/manual/eventlogging.adoc
@@ -0,0 +1,142 @@
+////
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements. See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License. You may obtain a copy of the License at
+
+        https://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+////
+= Log4j 2 API
+Ralph Goers <rg...@apache.org>
+
+[#EventLogging]
+== Event Logging
+
+The `EventLogger` class provides a simple mechanism 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.
+
+The recommended way of using the `EventLogger` in a typical 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 filter 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`.
+
+[source,java]
+----
+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 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() {
+    }
+}
+----
+
+Sample class that uses `EventLogger`.
+
+[source,java]
+----
+import org.apache.logging.log4j.StructuredDataMessage;
+import org.apache.logging.log4j.EventLogger;
+
+import java.util.Date;
+import java.util.UUID;
+
+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 StructuredDataMessage(confirm, null, "transfer");
+        msg.put("toAccount", toAccount);
+        msg.put("fromAccount", fromAccount);
+        msg.put("amount", amount);
+        EventLogger.logEvent(msg);
+        return confirm;
+    }
+}
+----
+
+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
+link:../log4j-core/apidocs/org/apache/logging/log4j/core/layout/StructuredDataLayout.html[`StructuredDataLayout`].

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7c855d1e/src/site/xdoc/manual/eventlogging.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/eventlogging.xml b/src/site/xdoc/manual/eventlogging.xml
deleted file mode 100644
index 8573499..0000000
--- a/src/site/xdoc/manual/eventlogging.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<document xmlns="http://maven.apache.org/XDOC/2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
-    <properties>
-        <title>Log4j 2 API</title>
-        <author email="rgoers@apache.org">Ralph Goers</author>
-    </properties>
-
-    <body>
-        <section name="Log4j 2 API">
-          <a name="EventLogging"/>
-          <subsection name="Event Logging">
-            <p>
-              The EventLogger class provides a simple mechanism 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 typical 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 filter 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>
-
-            <pre class="prettyprint linenums">
-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 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() {
-    }
-}</pre>
-            <p>Sample class that uses EventLogger.</p>
-            <pre class="prettyprint linenums">
-import org.apache.logging.log4j.StructuredDataMessage;
-import org.apache.logging.log4j.EventLogger;
-
-import java.util.Date;
-import java.util.UUID;
-
-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 StructuredDataMessage(confirm, null, "transfer");
-        msg.put("toAccount", toAccount);
-        msg.put("fromAccount", fromAccount);
-        msg.put("amount", amount);
-        EventLogger.logEvent(msg);
-        return confirm;
-    }
-}</pre>
-            <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 class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/layout/StructuredDataLayout.html">StructuredDataLayout</a>.
-            </p>
-          </subsection>
-        </section>
-    </body>
-</document>


[2/5] logging-log4j2 git commit: LOG4J2-1802: Convert flow tracing manual page to asciidoc

Posted by ma...@apache.org.
LOG4J2-1802: Convert flow tracing manual page to asciidoc


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/f000b5e3
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/f000b5e3
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/f000b5e3

Branch: refs/heads/master
Commit: f000b5e336ff31e5046b9e8791a1b28190639c22
Parents: 7c855d1
Author: Matt Sicker <bo...@gmail.com>
Authored: Sun Apr 8 13:46:35 2018 -0500
Committer: Matt Sicker <bo...@gmail.com>
Committed: Sun Apr 8 13:48:07 2018 -0500

----------------------------------------------------------------------
 src/site/asciidoc/manual/flowtracing.adoc | 275 +++++++++++++++++++++++++
 src/site/xdoc/manual/flowtracing.xml      | 268 ------------------------
 2 files changed, 275 insertions(+), 268 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f000b5e3/src/site/asciidoc/manual/flowtracing.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/manual/flowtracing.adoc b/src/site/asciidoc/manual/flowtracing.adoc
new file mode 100644
index 0000000..3fc318b
--- /dev/null
+++ b/src/site/asciidoc/manual/flowtracing.adoc
@@ -0,0 +1,275 @@
+////
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements. See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License. You may obtain a copy of the License at
+
+        https://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+////
+= Log4j 2 API
+Ralph Goers <rg...@apache.org>
+
+[#FlowTracing]
+== Flow Tracing
+
+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
+
+* aid in problem diagnosis in development without requiring a debug
+session
+* aid in problem diagnosis in production where no debugging is possible
+* help educate new developers in learning the application.
+
+The most used methods are the entry() or traceEntry() and exit() or
+traceExit() methods. entry() or traceEntry() should be placed at the
+beginning of methods, except perhaps for simple getters and setters.
+entry() can be called passing from 0 to 4 parameters. Typically these
+will be parameters passed to the method. traceEntry() can be passed a
+format String and a variable list of parameters, or a Message. The
+entry() and traceEntry() methods log with a level of TRACE and uses a
+Marker with a name of "ENTER" which is also a "FLOW" Marker and all
+message strings will begin with "event", even if a format String or
+Message is used.
+
+The main difference between the entry and traceEntry methods is that the
+entry method accepts a variable list of objects where presumably each is
+a method parameter. The traceEntry method accepts a format string
+followed by a variable list of objects, presumably included in the
+format String. It is not possible to have a single method that includes
+both of these as it would be ambiguous whether the first String is a
+parameter or a format String.
+
+An exit() or traceExit() method should be placed before any return
+statement or as the last statement of methods without a return. exit()
+and traceExit() can be called with or without a parameter. Typically,
+methods that return void will use exit() or traceExit() while methods
+that return an Object will use exit(Object obj) or traceExit(object, new
+SomeMessage(object)). The exit() and traceExit() methods log with a
+level of TRACE and uses a Marker with a name of "EXIT" which is also a
+"FLOW" Marker and all message strings will begin with "exit", even if a
+format String or Message is used.
+
+The throwing() method can be used by an application when it is throwing
+an exception that is unlikely to be handled, such as a RuntimeException.
+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.
+
+The catching() method can be used by an application when it catches an
+Exception that it is not going to rethrow, either explicitly 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.
+
+The following example shows a simple application using these methods in
+a fairly typical manner. The throwing() is not present since no
+Exceptions are explicitly thrown and not handled.
+
+[source,java]
+----
+package com.test;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+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 void setMessages(String[] messages) {
+        logger.traceEntry(new JsonMessage(messages));
+        this.messages = messages;
+        logger.traceExit();
+    }
+
+    public String[] getMessages() {
+        logger.traceEntry();
+        return logger.traceExit(messages, new JsonMessage(messages));
+    }
+
+    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);
+    }
+}
+----
+
+This test application uses the preceding service to generate logging
+events.
+
+[source,java]
+----
+package com.test;
+
+public class App {
+
+    public static void main( String[] args ) {
+        TestService service = new TestService();
+        service.retrieveMessage();
+        service.retrieveMessage();
+        service.exampleException();
+    }
+}
+----
+
+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.
+
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="error">
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
+      <!-- Flow tracing is most useful with a pattern that shows location.
+           Below pattern outputs class, line number and method name. -->
+      <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">
+      <AppenderRef ref="log"/>
+    </Root>
+  </Loggers>
+</Configuration>
+----
+
+Here is the output that results from the Java classes and configuration
+above.
+
+....
+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
+....
+
+Simply changing the root logger level to DEBUG in the example above will
+reduce the output considerably.
+
+....
+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]
+....

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f000b5e3/src/site/xdoc/manual/flowtracing.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/flowtracing.xml b/src/site/xdoc/manual/flowtracing.xml
deleted file mode 100644
index 916a9bb..0000000
--- a/src/site/xdoc/manual/flowtracing.xml
+++ /dev/null
@@ -1,268 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<document xmlns="http://maven.apache.org/XDOC/2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
-    <properties>
-        <title>Log4j 2 API</title>
-        <author email="rgoers@apache.org">Ralph Goers</author>
-    </properties>
-
-    <body>
-        <section name="Log4j 2 API">
-          <a name="FlowTracing"/>
-          <subsection name="Flow Tracing">
-            <p>
-              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
-            </p>
-            <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 developers in learning the application.</li>
-            </ul>
-            <p>
-              The most used methods are the entry() or traceEntry() and exit() or traceExit() methods. entry()
-              or traceEntry() should be placed at the beginning of methods, except perhaps for simple
-              getters and setters. entry() can be called passing from 0 to 4 parameters. Typically these will be
-              parameters passed to the method. traceEntry() can be passed a format String and a variable list of
-              parameters, or a Message. The entry() and traceEntry() methods log with a level of TRACE and uses
-              a Marker with a name of "ENTER" which is also a "FLOW" Marker and all message strings will begin
-              with "event", even if a format String or Message is used.
-            </p>
-            <p>The main difference between the entry and traceEntry methods is that the entry method accepts a
-              variable list of objects where presumably each is a method parameter. The traceEntry method
-              accepts a format string followed by a variable list of objects, presumably included in the
-              format String. It is not possible to have a single method that includes both of these as it would
-              be ambiguous whether the first String is a parameter or a format String.</p>
-            <p>
-              An exit() or traceExit() method should be placed before any return statement or as the last statement of
-              methods without a return. exit() and traceExit() can be called with or without a parameter. Typically,
-              methods that return void will use exit() or traceExit() while methods that return an Object will use
-              exit(Object obj) or traceExit(object, new SomeMessage(object)). The exit() and traceExit() methods log
-              with a level of TRACE and uses a Marker with a name of "EXIT" which is also a "FLOW" Marker and all
-              message strings will begin with "exit", even if a format String or Message is used.
-            </p>
-            <p>
-              The throwing() method can be used by an application when it is throwing an exception that is
-              unlikely to be handled, such as a RuntimeException. 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>
-            <p>
-              The catching() method can be used by an application when it catches an Exception that it is not
-              going to rethrow, either explicitly 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>
-            <p>
-              The following example shows a simple application using these methods in a fairly typical manner. The
-              throwing() is not present since no Exceptions are explicitly thrown and not handled.
-            </p>
-<pre class="prettyprint linenums">
-package com.test;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.LogManager;
-
-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 void setMessages(String[] messages) {
-        logger.traceEntry(new JsonMessage(messages));
-        this.messages = messages;
-        logger.traceExit();
-    }
-
-    public String[] getMessages() {
-        logger.traceEntry();
-        return logger.traceExit(messages, new JsonMessage(messages));
-    }
-
-    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);
-    }
-}</pre>
-            <p>
-              This test application uses the preceding service to generate logging events.
-            </p>
-<pre class="prettyprint linenums">
-package com.test;
-
-public class App {
-
-    public static void main( String[] args ) {
-        TestService service = new TestService();
-        service.retrieveMessage();
-        service.retrieveMessage();
-        service.exampleException();
-    }
-}</pre>
-            <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>
-<pre class="prettyprint linenums"><![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"/>
-      <!-- Flow tracing is most useful with a pattern that shows location.
-           Below pattern outputs class, line number and method name. -->
-      <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">
-      <AppenderRef ref="log"/>
-    </Root>
-  </Loggers>
-</Configuration>]]></pre>
-            <p>
-              Here is the output that results from the Java classes and configuration above.
-            </p>
-            <pre>
-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</pre>
-            <p>
-              Simply changing the root logger level to DEBUG in the example above will reduce the output
-              considerably.
-            </p>
-            <pre>
-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]</pre>
-          </subsection>
-        </section>
-    </body>
-</document>


[3/5] logging-log4j2 git commit: LOG4J2-1802: Convert markers manual page to asciidoc

Posted by ma...@apache.org.
LOG4J2-1802: Convert markers manual page to asciidoc


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/56eb7a04
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/56eb7a04
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/56eb7a04

Branch: refs/heads/master
Commit: 56eb7a040f259d814006088a79a884d411df48a9
Parents: f000b5e
Author: Matt Sicker <bo...@gmail.com>
Authored: Sun Apr 8 13:49:32 2018 -0500
Committer: Matt Sicker <bo...@gmail.com>
Committed: Sun Apr 8 13:49:32 2018 -0500

----------------------------------------------------------------------
 src/site/asciidoc/manual/markers.adoc | 104 +++++++++++++++++++++++++++
 src/site/xdoc/manual/markers.xml      | 110 -----------------------------
 2 files changed, 104 insertions(+), 110 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/56eb7a04/src/site/asciidoc/manual/markers.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/manual/markers.adoc b/src/site/asciidoc/manual/markers.adoc
new file mode 100644
index 0000000..ebf1b1d
--- /dev/null
+++ b/src/site/asciidoc/manual/markers.adoc
@@ -0,0 +1,104 @@
+////
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements. See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License. You may obtain a copy of the License at
+
+        https://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+////
+= Log4j 2 API
+Ralph Goers <rg...@apache.org>
+
+[#Markers]
+== Markers
+
+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:
+
+[source,java]
+----
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.MarkerManager;
+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").setParents(SQL_MARKER);
+    private static final Marker QUERY_MARKER = MarkerManager.getMarker("SQL_QUERY").setParents(SQL_MARKER);
+
+    public String doQuery(String table) {
+        logger.traceEntry();
+
+        logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);
+
+        String result = ... 
+
+        return logger.traceExit(result);
+    }
+
+    public String doUpdate(String table, Map<String, String> params) {
+        logger.traceEntry();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(UPDATE_MARKER, "UPDATE {} SET {}", table, formatCols());
+        }
+    
+        String result = ... 
+
+        return logger.traceExit(result);
+    }
+
+    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();
+    }
+}
+----
+
+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.
+
+Some important rules about Markers must be considered when using them.
+
+1.  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.
+2.  Parent Markers can be added or removed dynamically. However, this is
+fairly expensive to do. Instead, it is recommended that the parents be
+identified when obtaining the Marker the first time as shown in the
+examples above. Specifically, the set method replaces all the markers in
+a single operation while add and remove act on only a single Marker at a
+time.
+3.  Evaluating Markers with multiple ancestors is much more expensive
+than Markers with no parents. For example, in one set of tests to
+evaluate whether a Marker matched its grandparent took 3 times longer
+than evaluating the Marker itself. Even then though, evaluating Markers
+is inexpensive compared to resolving the callers class name or line
+number.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/56eb7a04/src/site/xdoc/manual/markers.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/markers.xml b/src/site/xdoc/manual/markers.xml
deleted file mode 100644
index 145eb97..0000000
--- a/src/site/xdoc/manual/markers.xml
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<document xmlns="http://maven.apache.org/XDOC/2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
-    <properties>
-        <title>Log4j 2 API</title>
-        <author email="rgoers@apache.org">Ralph Goers</author>
-    </properties>
-
-    <body>
-        <section name="Log4j 2 API">
-          <subsection name="Markers">
-            <a name="Markers"/>
-            <p>
-              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>
-        <pre class="prettyprint linenums"><![CDATA[
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.MarkerManager;
-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").setParents(SQL_MARKER);
-    private static final Marker QUERY_MARKER = MarkerManager.getMarker("SQL_QUERY").setParents(SQL_MARKER);
-
-    public String doQuery(String table) {
-        logger.traceEntry();
-
-        logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);
-
-        String result = ... 
-
-        return logger.traceExit(result);
-    }
-
-    public String doUpdate(String table, Map<String, String> params) {
-        logger.traceEntry();
-
-        if (logger.isDebugEnabled()) {
-            logger.debug(UPDATE_MARKER, "UPDATE {} SET {}", table, formatCols());
-        }
-	
-        String result = ... 
-
-        return logger.traceExit(result);
-    }
-
-    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();
-    }
-}]]></pre>
-            <p>
-              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>
-            <p>
-              Some important rules about Markers must be considered when using them.
-            </p>
-              <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>Parent Markers can be added or removed dynamically. However, this is fairly expensive to do.
-                  Instead, it is recommended that the parents be identified when obtaining the Marker the first time
-                  as shown in the examples above. Specifically, the set method replaces all the markers in
-                  a single operation while add and remove act on only a single Marker at a time.</li>
-                <li>Evaluating Markers with multiple ancestors is much more expensive than Markers with no parents.
-                  For example, in one set of tests to evaluate whether a Marker matched its grandparent took 3
-                  times longer than evaluating the Marker itself. Even then though, evaluating Markers is
-                  inexpensive compared to resolving the callers class name or line number.</li>
-              </ol>
-          </subsection>
-        </section>
-    </body>
-</document>


[5/5] logging-log4j2 git commit: LOG4J2-1802: Convert thread context manual page to asciidoc

Posted by ma...@apache.org.
LOG4J2-1802: Convert thread context manual page to asciidoc


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/71b1f20f
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/71b1f20f
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/71b1f20f

Branch: refs/heads/master
Commit: 71b1f20f68154d5138bdcc9c2d864ccc4a13f414
Parents: c34fa7e
Author: Matt Sicker <bo...@gmail.com>
Authored: Sun Apr 8 14:04:32 2018 -0500
Committer: Matt Sicker <bo...@gmail.com>
Committed: Sun Apr 8 14:04:32 2018 -0500

----------------------------------------------------------------------
 src/site/asciidoc/manual/thread-context.adoc | 233 ++++++++++++++++++++++
 src/site/xdoc/manual/thread-context.xml      | 209 -------------------
 2 files changed, 233 insertions(+), 209 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/71b1f20f/src/site/asciidoc/manual/thread-context.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/manual/thread-context.adoc b/src/site/asciidoc/manual/thread-context.adoc
new file mode 100644
index 0000000..e32cb79
--- /dev/null
+++ b/src/site/asciidoc/manual/thread-context.adoc
@@ -0,0 +1,233 @@
+////
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements. See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License. You may obtain a copy of the License at
+
+        https://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+////
+= Log4j 2 API
+Ralph Goers <rg...@apache.org>; Gary Gregory <gg...@apache.org>
+
+== Thread Context
+
+Log4j introduced the concept of the Mapped Diagnostic Context or MDC. It
+has been documented and discussed in numerous places including
+http://veerasundar.com/blog/2009/10/log4j-mdc-mapped-diagnostic-context-what-and-why/[Log4j
+MDC: What and Why] and
+http://blog.f12.no/wp/2004/12/09/log4j-and-the-mapped-diagnostic-context/[Log4j
+and the Mapped Diagnostic Context]. In addition, Log4j 1.x provides
+support for a Nested Diagnostic Context or NDC. It too has been
+documented and discussed in various places such as
+http://lstierneyltd.com/blog/development/log4j-nested-diagnostic-contexts-ndc/[Log4j
+NDC]. SLF4J/Logback followed with its own implementation of the MDC,
+which is documented very well at
+http://logback.qos.ch/manual/mdc.html[Mapped Diagnostic Context].
+
+Log4j 2 continues with the idea of the MDC and the NDC but merges them
+into a single Thread Context. The Thread Context Map is the equivalent
+of the MDC and the Thread Context Stack is the equivalent of the 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.
+
+=== Fish Tagging
+
+Most real-world systems have to deal with multiple clients
+simultaneously. In a typical multithreaded implementation of such a
+system, different threads will handle different clients. Logging is
+especially well suited to trace and debug complex distributed
+applications. A common approach to differentiate the logging output of
+one client from another is to instantiate a new separate logger for each
+client. This promotes the proliferation of loggers and increases the
+management overhead of logging.
+
+A lighter technique is to uniquely stamp each log request initiated from
+the same client interaction. Neil Harrison described this method in the
+book "Patterns for Logging Diagnostic Messages," in _Pattern Languages
+of Program Design 3_, edited by R. Martin, D. Riehle, and F. Buschmann
+(Addison-Wesley, 1997). Just as a fish can be tagged and have its
+movement tracked, stamping log events with a common tag or set of data
+elements allows the complete flow of a transaction or a request to be
+tracked. We call this _Fish Tagging_.
+
+Log4j provides two mechanisms for performing Fish Tagging; the Thread
+Context Map and the Thread Context Stack. The Thread Context Map allows
+any number of items to be added and be identified using key/value pairs.
+The Thread Context Stack allows one or more items to be pushed on the
+Stack and then be identified by their order in the Stack or by the data
+itself. Since key/value pairs are more flexible, the Thread Context Map
+is recommended when data items may be added during the processing of the
+request or when there are more than one or two items.
+
+To uniquely stamp each request using the Thread Context Stack, the user
+pushes contextual information on to the Stack.
+
+[source,java]
+----
+ThreadContext.push(UUID.randomUUID().toString()); // Add the fishtag;
+
+logger.debug("Message 1");
+
+// ...
+
+logger.debug("Message 2");.
+
+// ...
+
+ThreadContext.pop();
+----
+
+The alternative to the Thread Context Stack is the Thread Context Map.
+In this case, attributes associated with the request being processed are
+adding at the beginning and removed at the end as follows:
+
+[source,java]
+----
+ThreadContext.put("id", UUID.randomUUID().toString()); // Add the fishtag;
+ThreadContext.put("ipAddress", request.getRemoteAddr());
+ThreadContext.put("loginId", session.getAttribute("loginId"));
+ThreadContext.put("hostName", request.getServerName());
+
+// ...
+
+logger.debug("Message 1");
+
+// ...
+
+logger.debug("Message 2");
+
+// ...
+
+ThreadContext.clear();
+----
+
+=== CloseableThreadContext
+
+When placing items on the stack or map, it's necessary to remove then
+again when appropriate. To assist with this, the
+`CloseableThreadContext` implements the
+http://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html[`AutoCloseable`
+interface]. This allows items to be pushed to the stack or put in the
+map, and removed when the `close()` method is called - or automatically
+as part of a try-with-resources. For example, to temporarily push
+something on to the stack and then remove it:
+
+[source,java]
+----
+// Add to the ThreadContext stack for this try block only;
+try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.push(UUID.randomUUID().toString())) {
+
+    logger.debug("Message 1");
+
+// ...
+
+    logger.debug("Message 2");
+
+// ...
+
+}
+----
+
+Or, to temporarily put something in the map:
+
+[source,java]
+----
+// Add to the ThreadContext map for this try block only;
+try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.put("id", UUID.randomUUID().toString())
+                                                                .put("loginId", session.getAttribute("loginId"))) {
+
+    logger.debug("Message 1");
+
+// ...
+
+    logger.debug("Message 2");
+
+// ...
+
+}
+----
+
+If you're using a thread pool, then you can initialise a
+CloseableThreadContext by using the
+`putAll(final Map<String, String> values)` and/or
+`pushAll(List<String> messages)` methods;
+
+[source,java]
+----
+for( final Session session : sessions ) {
+    try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.put("loginId", session.getAttribute("loginId"))) {
+        logger.debug("Starting background thread for user");
+        final Map<String, String> values = ThreadContext.getImmutableContext();
+        final List<String> messages = ThreadContext.getImmutableStack().asList();
+        executor.submit(new Runnable() {
+        public void run() {
+            try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.putAll(values).pushAll(messages)) {
+                logger.debug("Processing for user started");
+
+// ...
+
+                logger.debug("Processing for user completed");
+            }
+        });
+    }
+}
+----
+
+=== Implementation details
+
+The Stack and the Map are managed per thread and are based on
+http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html[`ThreadLocal`]
+by default. The Map can be configured to use an
+http://docs.oracle.com/javase/6/docs/api/java/lang/InheritableThreadLocal.html[`InheritableThreadLocal`]
+by setting system property `log4j2.isThreadContextMapInheritable` to
+`true`. When configured this way, the contents of the Map will be passed
+to child threads. However, as discussed in the
+http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#privilegedThreadFactory()[`Executors`]
+class and in other cases where thread pooling is utilized, the
+ThreadContext may not always be automatically passed to worker threads.
+In those cases the pooling mechanism should provide a means for doing
+so. The `getContext()` and `cloneStack()` methods can be used to obtain
+copies of the Map and Stack respectively.
+
+Note that all methods of the
+link:../log4j-api/apidocs/org/apache/logging/log4j/ThreadContext.html[`ThreadContext`]
+class are static.
+
+=== Including the ThreadContext when writing logs
+
+The
+link:../log4j-api/apidocs/org/apache/logging/log4j/core/PatternLayout.html[`PatternLayout`]
+provides mechanisms to print the contents of the
+link:../log4j-api/apidocs/org/apache/logging/log4j/ThreadContext.html[`ThreadContext`]
+Map and Stack.
+
+* Use `%X` by itself to include the full contents of the Map.
+* Use `%X{key}` to include the specified key.
+* Use `%x` to include the full contents of the
+http://docs.oracle.com/javase/6/docs/api/java/util/Stack.html[Stack].
+
+=== Custom context data injectors for non thread-local context data
+
+With the ThreadContext logging statements can be tagged so log entries
+that were related in some way can be linked via these tags. The
+limitation is that this only works for logging done on the same
+application thread (or child threads when configured).
+
+Some applications have a thread model that delegates work to other
+threads, and in such models, tagging attributes that are put into a
+thread-local map in one thread are not visible in the other threads and
+logging done in the other threads will not show these attributes.
+
+Log4j 2.7 adds a flexible mechanism to tag logging statements with
+context data coming from other sources than the ThreadContext. See the
+manual page on link:extending.html#Custom_ContextDataInjector[extending
+Log4j] for details.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/71b1f20f/src/site/xdoc/manual/thread-context.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/thread-context.xml b/src/site/xdoc/manual/thread-context.xml
deleted file mode 100644
index 5867c38..0000000
--- a/src/site/xdoc/manual/thread-context.xml
+++ /dev/null
@@ -1,209 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<document xmlns="http://maven.apache.org/XDOC/2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
-    <properties>
-        <title>Log4j 2 Thread Context</title>
-        <author email="rgoers@apache.org">Ralph Goers</author>
-        <author email="ggregory@apache.org">Gary Gregory</author>
-    </properties>
-
-    <body>
-      <section name="Log4j 2 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
-            <a href="http://blog.f12.no/wp/2004/12/09/log4j-and-the-mapped-diagnostic-context/">Log4j and the Mapped Diagnostic Context</a>.
-            In addition, Log4j 1.x provides support for a Nested Diagnostic Context or NDC. It too has been documented
-            and discussed in various places such as
-            <a href="http://lstierneyltd.com/blog/development/log4j-nested-diagnostic-contexts-ndc/">Log4j NDC</a>.
-            SLF4J/Logback followed with its own implementation of the MDC, which is documented very well at
-            <a href="http://logback.qos.ch/manual/mdc.html">Mapped Diagnostic Context</a>.
-          </p>
-          <p>Log4j 2 continues with the idea of the MDC and the NDC but merges them into a single Thread Context.
-            The Thread Context Map is the equivalent of the MDC and the Thread Context Stack is the equivalent of the
-            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>
-          <h4>Fish Tagging</h4>
-          <p>Most real-world systems have to deal with multiple clients simultaneously. In a typical multithreaded
-            implementation of such a system, different threads will handle different clients. Logging is
-            especially well suited to trace and debug complex distributed applications. A common approach to
-            differentiate the logging output of one client from another is to instantiate a new separate logger for
-            each client. This promotes the proliferation of loggers and increases the management overhead of logging.
-          </p>
-          <p>A lighter technique is to uniquely stamp each log request initiated from the same client interaction.
-            Neil Harrison described this method in the book "Patterns for Logging Diagnostic Messages," in <em>Pattern
-            Languages of Program Design 3</em>, edited by R. Martin, D.  Riehle, and F. Buschmann
-            (Addison-Wesley, 1997). Just as a fish can be tagged and have its movement tracked, stamping log
-            events with a common tag or set of data elements allows the complete flow of a transaction or a request
-            to be tracked. We call this <i>Fish Tagging</i>.
-          </p>
-          <p>Log4j provides two mechanisms for performing Fish Tagging; the Thread Context Map and the Thread
-            Context Stack. The Thread Context Map allows any number of items to be added and be identified
-            using key/value pairs. The Thread Context Stack allows one or more items to be pushed on the
-            Stack and then be identified by their order in the Stack or by the data itself. Since key/value
-            pairs are more flexible, the Thread Context Map is recommended when data items may be added during
-            the processing of the request or when there are more than one or two items.
-          </p>
-           <p>To uniquely stamp each request using the Thread Context Stack, the user pushes contextual information
-             on to the Stack.
-           </p>
-            <pre class="prettyprint linenums">
-ThreadContext.push(UUID.randomUUID().toString()); // Add the fishtag;
-
-logger.debug("Message 1");
-.
-.
-.
-logger.debug("Message 2");
-.
-.
-ThreadContext.pop();</pre>
-          <p>
-            The alternative to the Thread Context Stack is the Thread Context Map. In this case, attributes
-            associated with the request being processed are adding at the beginning and removed at the end
-            as follows:
-          </p>
-          <pre class="prettyprint linenums">
-ThreadContext.put("id", UUID.randomUUID().toString()); // Add the fishtag;
-ThreadContext.put("ipAddress", request.getRemoteAddr());
-ThreadContext.put("loginId", session.getAttribute("loginId"));
-ThreadContext.put("hostName", request.getServerName());
-.
-logger.debug("Message 1");
-.
-.
-logger.debug("Message 2");
-.
-.
-ThreadContext.clear();</pre>
-
-          <h4>CloseableThreadContext</h4>
-		  <p>When placing items on the stack or map, it's necessary to remove then again when appropriate. To assist with
-		  this, the <tt>CloseableThreadContext</tt> implements the <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html">AutoCloseable
-		  interface</a>. This allows items to be pushed to the stack or put in the map, and removed when the <tt>close()</tt> method is called -
-		  or automatically as part of a try-with-resources. For example, to temporarily push something on to the stack and then remove it:
-          </p>
-		  <pre class="prettyprint linenums">
-// Add to the ThreadContext stack for this try block only;
-try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.push(UUID.randomUUID().toString())) {
-
-    logger.debug("Message 1");
-.
-.
-    logger.debug("Message 2");
-.
-.
-}</pre>
-          <p>
-          Or, to temporarily put something in the map:
-          </p>
-		  <pre class="prettyprint linenums">
-// Add to the ThreadContext map for this try block only;
-try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.put("id", UUID.randomUUID().toString())
-                                                                .put("loginId", session.getAttribute("loginId"))) {
-
-    logger.debug("Message 1");
-.
-.
-    logger.debug("Message 2");
-.
-.
-}</pre>
-
-            If you're using a thread pool, then you can initialise a CloseableThreadContext by using the
-            <tt>putAll(final Map&lt;String, String&gt; values)</tt> and/or
-            <tt>pushAll(List&lt;String&gt; messages)</tt> methods;
-            <pre class="prettyprint linenums">
-for( final Session session : sessions ) {
-    try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.put("loginId", session.getAttribute("loginId"))) {
-        logger.debug("Starting background thread for user");
-        final Map&lt;String, String&gt; values = ThreadContext.getImmutableContext();
-        final List&lt;String&gt; messages = ThreadContext.getImmutableStack().asList();
-        executor.submit(new Runnable() {
-        public void run() {
-            try (final CloseableThreadContext.Instance ctc = CloseableThreadContext.putAll(values).pushAll(messages)) {
-                logger.debug("Processing for user started");
-                .
-                logger.debug("Processing for user completed");
-            }
-        });
-    }
-}</pre>
-		  <h4>Implementation details</h4>
-          <p>The Stack and the Map are managed per thread and are based on
-            <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html">ThreadLocal</a>
-            by default. The Map can be configured to use an
-            <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/InheritableThreadLocal.html">InheritableThreadLocal</a>
-            by setting system property <tt>log4j2.isThreadContextMapInheritable</tt> to <tt>true</tt>.
-            When configured this way, the contents of the Map will be passed to child threads. However, as
-            discussed in the
-            <a href="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#privilegedThreadFactory()">Executors</a>
-            class and in other cases where thread pooling is utilized, the ThreadContext may not always be
-            automatically passed to worker threads. In those cases the pooling mechanism should provide a means for
-            doing so. The getContext() and cloneStack() methods can be used to obtain copies of the Map and Stack
-            respectively.
-          </p>
-          <p>
-            Note that all methods of the
-            <a href="../log4j-api/apidocs/org/apache/logging/log4j/ThreadContext.html">ThreadContext</a>
-            class are static.
-          </p>
-          <h4>Including the ThreadContext when writing logs</h4>
-          <p>
-            The <a href="../log4j-api/apidocs/org/apache/logging/log4j/core/PatternLayout.html">PatternLayout</a>
-            provides mechanisms to print the contents of the
-            <a href="../log4j-api/apidocs/org/apache/logging/log4j/ThreadContext.html">ThreadContext</a>
-            Map and Stack.
-          </p>
-          <ul>
-            <li>
-              Use <code>%X</code> by itself to include the full contents of the Map.
-            </li>
-            <li>
-              Use <code>%X{key}</code> to include the specified key.
-            </li>
-            <li>
-              Use <code>%x</code> to include the full contents of the <a href="http://docs.oracle.com/javase/6/docs/api/java/util/Stack.html">Stack</a>.
-            </li>
-          </ul>
-          <h4>Custom context data injectors for non thread-local context data</h4>
-          <p>
-            With the ThreadContext logging statements can be tagged so log entries that were related in some way
-            can be linked via these tags. The limitation is that this only works for logging done on the same application thread
-            (or child threads when configured).
-          </p>
-          <p>
-            Some applications have a thread model that delegates work to other threads, and
-            in such models, tagging attributes that are put into a thread-local map in one thread are not visible
-            in the other threads and logging done in the other threads will not show these attributes.
-          </p>
-          <p>
-            Log4j 2.7 adds a flexible mechanism to tag logging statements with context data coming from
-            other sources than the ThreadContext.
-            See the manual page on <a href="extending.html#Custom_ContextDataInjector">extending Log4j</a> for details.
-          </p>
-        </subsection>
-      </section>
-    </body>
-</document>


[4/5] logging-log4j2 git commit: LOG4J2-1802: Convert messages manual page to asciidoc

Posted by ma...@apache.org.
LOG4J2-1802: Convert messages manual page to asciidoc


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/c34fa7ef
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/c34fa7ef
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/c34fa7ef

Branch: refs/heads/master
Commit: c34fa7efaa75f41ecdbae5ca426c2529738f2d86
Parents: 56eb7a0
Author: Matt Sicker <bo...@gmail.com>
Authored: Sun Apr 8 13:59:27 2018 -0500
Committer: Matt Sicker <bo...@gmail.com>
Committed: Sun Apr 8 13:59:27 2018 -0500

----------------------------------------------------------------------
 src/site/asciidoc/manual/messages.adoc | 333 ++++++++++++++++++++++++++++
 src/site/xdoc/manual/messages.xml      | 314 --------------------------
 2 files changed, 333 insertions(+), 314 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c34fa7ef/src/site/asciidoc/manual/messages.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/manual/messages.adoc b/src/site/asciidoc/manual/messages.adoc
new file mode 100644
index 0000000..8c27dc3
--- /dev/null
+++ b/src/site/asciidoc/manual/messages.adoc
@@ -0,0 +1,333 @@
+////
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements. See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License. You may obtain a copy of the License at
+
+        https://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+////
+= Log4j 2 API
+Ralph Goers <rg...@apache.org>
+
+[#Messages]
+== Messages
+
+Although Log4j 2 provides Logger methods that accept Strings and
+Objects, all of these are ultimately captured in Message objects that
+are then associated with the log event. Applications are free to
+construct Messages of their own and pass them to the Logger. Although it
+may seem more expensive than passing the message format and parameters
+directly to the event, testing has shown that with modern JVMs the cost
+of creating and destroying events is minor, especially when complex
+tasks are encapsulated in the Message instead of the application. In
+addition, when using the methods that accept Strings and parameters, the
+underlying Message object will only be created if any configured global
+filters or the Logger's log level allow the message to be processed.
+
+Consider an application that has a Map object containing \{"Name" =
+"John Doe", "Address" = "123 Main St.", "Phone" = "(999) 555-1212"} and
+a User object that has a getId method that returns "jdoe". The developer
+would like to add an informational message that returns "User John Doe
+has logged in using id jdoe". The way this could be accomplished is by
+doing:
+
+[source,java]
+----
+logger.info("User {} has logged in using id {}", map.get("Name"), user.getId());
+----
+
+While there is nothing inherently wrong with this, as the complexity of
+the objects and desired output increases this technique becomes harder
+to use. As an alternative, using Messages allows:
+
+[source,java]
+----
+logger.info(new LoggedInMessage(map, user));
+----
+
+In this alternative the formatting is delegated to the `LoggedInMessage`
+object's `getFormattedMessage` method. Although in this alternative a new
+object is created, none of the methods on the objects passed to the
+`LoggedInMessage` are invoked until the `LoggedInMessage` is formatted. This
+is especially useful when an `Object`'s `toString` method does not produce
+the information you would like to appear in the log.
+
+Another advantage to Messages is that they simplify writing Layouts. In
+other logging frameworks the Layout must loop through the parameters
+individually and determine what to do based on what objects 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.
+
+Borrowing from the earlier example illustrating Markers to identify SQL
+statements being logged, Messages can also be leveraged. First, the
+Message is defined.
+
+[source,java]
+----
+public class SQLMessage implements Message {
+  public enum SQLType {
+      UPDATE,
+      QUERY
+  };
+
+  private 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();
+  }
+}
+----
+
+Next we can use the message in our application.
+
+[source,java]
+----
+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();
+    }
+}
+----
+
+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.
+
+[#FormattedMessage]
+=== FormattedMessage
+
+The message pattern passed to a
+link:../log4j-api/apidocs/org/apache/logging/log4j/message/FormattedMessage.html[`FormattedMessage`]
+is first checked to see if it is a valid `java.text.MessageFormat`
+pattern. If it is, a `MessageFormatMessage` is used to format it. If not
+it is next checked to see if it contains any tokens that are valid
+format specifiers for `String.format()`. If so, a `StringFormattedMessage`
+is used to format it. Finally, if the pattern doesn't match either of
+those then a `ParameterizedMessage` is used to format it.
+
+[#LocalizedMessage]
+=== LocalizedMessage
+
+link:../log4j-api/apidocs/org/apache/logging/log4j/message/LocalizedMessage.html[`LocalizedMessage`]
+is provided primarily to provide compatibility with Log4j 1.x.
+Generally, the best approach to localization is to have the client UI
+render the events in the client's locale.
+
+`LocalizedMessage` incorporates a `ResourceBundle` and allows the message
+pattern parameter to be the key to the message pattern in the bundle. If
+no bundle is specified, `LocalizedMessage` will attempt to locate a bundle
+with the name of the Logger used to log the event. The message retrieved
+from the bundle will be formatted using a FormattedMessage.
+
+[#LoggerNameAwareMessage]
+=== LoggerNameAwareMessage
+
+`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.
+
+[#MapMessage]
+=== MapMessage
+
+A `MapMessage` contains a Map of String keys and values. `MapMessage`
+implements `FormattedMessage` and accepts format specifiers of "XML",
+"JSON" or "JAVA", in which case the Map will be formatted as XML, JSON
+or as documented by
+https://docs.oracle.com/javase/7/docs/api/java/util/AbstractMap.html#toString()[`java.util.AbstractMap.toString()`].
+Otherwise, the Map will be formatted as `"key1=value1 key2=value2 ..."`.
+
+Some Appenders make special use of `MapMessage` objects:
+
+* When a link:appenders.html#JMSAppender[JMS Appender] is configured
+with a `MessageLayout`, it converts a Log4j `MapMessage` to a JMS
+`javax.jms.MapMessage`.
+* When a link:appenders.html#JDBCAppender[JDBC Appender] is configured
+with a `MessageLayout`, it converts a Log4j `MapMessage` to values in a
+SQL INSERT statement.
+* When a link:appenders.html#NoSQLAppenderMongoDB2[MongoDB2 Appender] or
+link:appenders.html#NoSQLAppenderMongoDB3[MongoDB3 Appender] is
+configured with a `MessageLayout`, it converts a Log4j `MapMessage` to
+fields in a MongoDB object.
+
+When an Appender is `MessageLayout`-aware, the object Log4j sends to
+target is not a Log4j Log Event but a custom object.
+
+[#MessageFormatMessage]
+=== MessageFormatMessage
+
+link:../log4j-api/apidocs/org/apache/logging/log4j/message/MessageFormatMessage.html[`MessageFormatMessage`]
+handles messages that use a
+https://docs.oracle.com/javase/7/docs/api/java/text/MessageFormat.html[conversion
+format]. While this `Message` has more flexibility than
+`ParameterizedMessage`, it is also about two times slower.
+
+[#MultiformatMessage]
+=== MultiformatMessage
+
+A `MultiformatMessage` will have a getFormats method and a
+`getFormattedMessage` method that accepts and array of format Strings. The
+`getFormats` method may be called by a Layout to provide it information on
+what formatting options the Message supports. The Layout may then call
+`getFormattedMessage` with one or more for the formats. If the Message
+doesn't recognize the format name it will simply format the data using
+its default format. An example of this is `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.
+
+[#ObjectMessage]
+=== ObjectMessage
+
+Formats an `Object` by calling its `toString` method. Since Log4j 2.6,
+Layouts trying to be low-garbage or garbage-free will call the
+`formatTo(StringBuilder)` method instead.
+
+[#ParameterizedMessage]
+=== ParameterizedMessage
+
+link:../log4j-api/apidocs/org/apache/logging/log4j/message/ParameterizedMessage.html[`ParameterizedMessage`]
+handles messages that contain "\{}" in the format to represent
+replaceable tokens and the replacement parameters.
+
+[#ReusableObjectMessage]
+=== ReusableObjectMessage
+
+In garbage-free mode, this message is used to pass logged Objects to the
+Layout and Appenders. Functionally equivalent to
+<<ObjectMessage>>.
+
+[#ReusableParameterizedMessage]
+=== ReusableParameterizedMessage
+
+In garbage-free mode, this message is used to handle messages that
+contain "\{}" in the format to represent replaceable tokens and the
+replacement parameters. Functionally equivalent to
+<<ParameterizedMessage>>.
+
+[#ReusableSimpleMessage]
+=== ReusableSimpleMessage
+
+In garbage-free mode, this message is used to pass logged `String`s and
+`CharSequence`s to the Layout and Appenders. Functionally equivalent to
+<<SimpleMessage>>.
+
+[#SimpleMessage]
+=== SimpleMessage
+
+`SimpleMessage` contains a `String` or `CharSequence` that requires no
+formatting.
+
+[#StringFormattedMessage]
+=== StringFormattedMessage
+
+link:../log4j-api/apidocs/org/apache/logging/log4j/message/StringFormattedMessage.html[`StringFormattedMessage`]
+handles messages that use a
+https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax[conversion
+format] that is compliant with
+https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#format(java.lang.String,%20java.lang.Object...)[java.lang.String.format()].
+While this Message has more flexibility than `ParameterizedMessage`, it is
+also 5 to 10 times slower.
+
+[#StructuredDataMessage]
+=== StructuredDataMessage
+
+link:../log4j-api/apidocs/org/apache/logging/log4j/message/StructuredDataMessage.html[`StructuredDataMessage`]
+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 http://tools.ietf.org/html/rfc5424[RFC 5424].
+
+[#ThreadDumpMessage]
+=== ThreadDumpMessage
+
+A ThreadDumpMessage, if logged, will generate stack traces for all
+threads. The stack traces will include any locks that are held.
+
+[#TimestampMessage]
+=== TimestampMessage
+
+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.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c34fa7ef/src/site/xdoc/manual/messages.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/messages.xml b/src/site/xdoc/manual/messages.xml
deleted file mode 100644
index 9eef316..0000000
--- a/src/site/xdoc/manual/messages.xml
+++ /dev/null
@@ -1,314 +0,0 @@
-<?xml version="1.0"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<document xmlns="http://maven.apache.org/XDOC/2.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
-  <properties>
-    <title>Log4j 2 API Messages</title>
-    <author email="rgoers@apache.org">Ralph Goers</author>
-  </properties>
-
-  <body>
-    <section name="Log4j 2 API">
-      <subsection name="Messages">
-        <a name="Messages"/>
-        <p>
-          Although Log4j 2 provides Logger methods that accept Strings and Objects, all of these are ultimately
-          captured in Message objects that are then associated with the log event. Applications are free to
-          construct Messages of their own and pass them to the Logger. Although it may seem more expensive than
-          passing the message format and parameters directly to the event, testing has shown that with modern
-          JVMs the cost of creating and destroying events is minor, especially when complex tasks are encapsulated
-          in the Message instead of the application. In addition, when using the methods that accept Strings and
-          parameters, the underlying Message object will only be created if any configured global filters
-          or the Logger's log level allow the message to be processed.
-        </p>
-        <p>
-          Consider an application that has a Map object containing {"Name" = "John Doe", "Address" = "123 Main
-          St.",
-          "Phone" = "(999) 555-1212"} and a User object that has a getId method that returns "jdoe". The developer
-          would like to add an informational message that returns "User John Doe has logged in using id jdoe". The
-          way this could be accomplished is by doing:
-        </p>
-        <pre class="prettyprint">logger.info("User {} has logged in using id {}", map.get("Name"), user.getId());</pre>
-        <p>
-          While there is nothing inherently wrong with this, as the complexity of the objects and desired output
-          increases this technique becomes harder to use. As an alternative, using Messages allows:
-        </p>
-        <pre class="prettyprint">logger.info(new LoggedInMessage(map, user));</pre>
-        <p>
-          In this alternative the formatting is delegated to the LoggedInMessage object's getFormattedMessage
-          method.
-          Although in this alternative a new object is created, none of the methods on the objects passed to the
-          LoggedInMessage are invoked until the LoggedInMessage is formatted. This is especially useful when an
-          Object's toString method does not produce the information you would like to appear in the log.
-        </p>
-        <p>
-          Another advantage to Messages is that they simplify writing Layouts. In other logging frameworks the
-          Layout must loop through the parameters individually and determine what to do based on what objects
-          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>
-        <pre class="prettyprint linenums"><![CDATA[
-public class SQLMessage implements Message {
-  public enum SQLType {
-      UPDATE,
-      QUERY
-  };
-
-  private 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();
-  }
-}]]></pre>
-      <p>
-        Next we can use the message in our application.
-      </p>
-        <pre class="prettyprint linenums"><![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();
-    }
-}]]></pre>
-        <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>
-      <h4>FormattedMessage</h4>
-        <a name="FormattedMessage"/>
-        <p>
-          The message pattern passed to a
-          <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/message/FormattedMessage.html">FormattedMessage</a>
-          is first checked to see if it is a valid java.text.MessageFormat pattern. If it is, a MessageFormatMessage is
-          used to format it. If not it is next checked to see if it contains any tokens that are valid format
-          specifiers for String.format(). If so, a StringFormattedMessage is used to format it. Finally, if the
-          pattern doesn't match either of those then a ParameterizedMessage is used to format it.
-        </p>
-      <h4>LocalizedMessage</h4>
-        <a name="LocalizedMessage"/>
-        <p>
-          <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/message/LocalizedMessage.html">LocalizedMessage</a>
-          is provided primarily to provide compatibility with Log4j 1.x. Generally,
-          the best approach to localization is to have the client UI render the events in the client's locale.
-        </p>
-        <p>
-          LocalizedMessage incorporates a ResourceBundle and allows the message pattern parameter to be the key to
-          the message pattern in the bundle. If no bundle is specified,
-          LocalizedMessage will attempt to locate a bundle with the name of the Logger used to log the event. The
-          message retrieved from the bundle will be formatted using a FormattedMessage.
-        </p>
-      <h4>LoggerNameAwareMessage</h4>
-        <a name="LoggerNameAwareMessage"/>
-        <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>
-      <h4>MapMessage</h4>
-        <a name="MapMessage"/>
-        <p>
-          A <code>MapMessage</code> contains a Map of String keys and values. <code>MapMessage</code> implements 
-          <code>FormattedMessage</code> and accepts format specifiers of "XML", "JSON" or "JAVA", in which case the Map
-          will be formatted as XML, JSON or as documented by
-          <a class="javadoc" href="https://docs.oracle.com/javase/7/docs/api/java/util/AbstractMap.html#toString()">java.util.AbstractMap.toString()</a>.
-          Otherwise, the Map will be formatted as <code>"key1=value1 key2=value2 ..."</code>.
-        </p>
-        <p>
-          Some Appenders make special use of <code>MapMessage</code> objects: 
-        </p>
-        <ul>
-          <li>
-            When a <a href="appenders.html#JMSAppender">JMS Appender</a> is configured with a <code>MessageLayout</code>, it converts a Log4j 
-            <code>MapMessage</code> to a JMS <code>javax.jms.MapMessage</code>.
-          </li>
-          <li>
-            When a <a href="appenders.html#JDBCAppender">JDBC Appender</a> is configured with a <code>MessageLayout</code>, it converts a Log4j 
-            <code>MapMessage</code> to values in a SQL INSERT statement.
-          </li>
-          <li>
-            When a <a href="appenders.html#NoSQLAppenderMongoDB2">MongoDB2 Appender</a> or 
-            <a href="appenders.html#NoSQLAppenderMongoDB3">MongoDB3 Appender</a> is configured with a <code>MessageLayout</code>, it converts a Log4j 
-            <code>MapMessage</code> to fields in a MongoDB object. 
-          </li>
-        </ul>
-        <p>
-          When an Appender is <code>MessageLayout</code>-aware, the object Log4j sends to target is not a Log4j Log 
-          Event but a custom object.
-        </p>
-        <h4>MessageFormatMessage</h4>
-        <a name="MessageFormatMessage"/>
-        <p>
-          <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/message/MessageFormatMessage.html">MessageFormatMessage</a>
-          handles messages that use a <a href="https://docs.oracle.com/javase/7/docs/api/java/text/MessageFormat.html">conversion format</a>.
-          While this Message has more flexibility than ParameterizedMessage, it is also about two times slower.
-        </p>
-      <h4>MultiformatMessage</h4>
-        <a name="MultiformatMessage"/>
-        <p>
-          A MultiformatMessage will have a getFormats method and a getFormattedMessage method that accepts and array
-          of format Strings. The getFormats method may be called by a Layout to provide it information on what
-          formatting options the Message supports. The Layout may then call getFormattedMessage with one or more
-          for the formats. If the Message doesn't recognize the format name it will simply format the data using its
-          default format. An example of this is the 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>
-      <h4>ObjectMessage</h4>
-        <a name="ObjectMessage"/>
-        <p>
-          Formats an Object by calling its toString method. Since Log4j 2.6, Layouts trying to be low-garbage or
-          garbage-free will call the <tt>formatTo(StringBuilder)</tt> method instead.
-        </p>
-      <h4>ParameterizedMessage</h4>
-        <a name="ParameterizedMessage"/>
-        <p>
-          <a class="javadoc" href="../log4j-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>
-      <h4>ReusableObjectMessage</h4>
-        <a name="ReusableObjectMessage"/>
-        <p>
-          In garbage-free mode, this message is used to pass logged Objects to the Layout and Appenders.
-          Functionally equivalent to <a href="#ObjectMessage">ObjectMessage</a>.
-        </p>
-      <h4>ReusableParameterizedMessage</h4>
-        <a name="ReusableParameterizedMessage"/>
-        <p>
-          In garbage-free mode, this message is used to handle messages that contain "{}" in the format to
-          represent replaceable tokens and the replacement parameters.
-          Functionally equivalent to <a href="#ParameterizedMessage">ParameterizedMessage</a>.
-        </p>
-      <h4>ReusableSimpleMessage</h4>
-        <a name="ReusableSimpleMessage"/>
-        <p>
-          In garbage-free mode, this message is used to pass logged Strings and CharSequences to the Layout and Appenders.
-          Functionally equivalent to <a href="#SimpleMessage">SimpleMessage</a>.
-        </p>
-      <h4>SimpleMessage</h4>
-        <a name="SimpleMessage"/>
-        <p>
-          SimpleMessage contains a String or CharSequence that requires no formatting.
-        </p>
-      <h4>StringFormattedMessage</h4>
-        <a name="StringFormattedMessage"/>
-        <p>
-          <a class="javadoc" href="../log4j-api/apidocs/org/apache/logging/log4j/message/StringFormattedMessage.html">StringFormattedMessage</a>
-          handles messages that use a <a href="https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">conversion format</a>
-          that is compliant with <a class="javadoc" href="https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#format(java.lang.String, java.lang.Object...)">java.lang.String.format()</a>.
-          While this Message has more flexibility than ParameterizedMessage, it is also 5 to 10 times slower.
-        </p>
-      <h4>StructuredDataMessage</h4>
-        <a name="StructuredDataMessage"/>
-        <p>
-          <a class="javadoc" href="../log4j-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>
-      <h4>ThreadDumpMessage</h4>
-        <a name="ThreadDumpMessage"/>
-        <p>
-          A ThreadDumpMessage, if logged, will generate stack traces for all threads.
-          The stack traces will include any locks that are held.
-        </p>
-      <h4>TimestampMessage</h4>
-        <a name="TimestampMessage"/>
-        <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.
-        </p>
-      </subsection>
-    </section>
-  </body>
-</document>