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<String, String> values)</tt> and/or
- <tt>pushAll(List<String> 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<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");
- }
- });
- }
-}</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>