You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2024/05/27 07:59:52 UTC
(logging-log4j2) 02/03: Redirect API-related pages to Log4j 2
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 6d2c4da069b31848ee96aaed2223bf0bd7820d52
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Mon May 27 09:36:40 2024 +0200
Redirect API-related pages to Log4j 2
---
src/site/antora/antora.tmpl.yml | 1 +
src/site/antora/antora.yml | 1 +
src/site/antora/modules/ROOT/nav.adoc | 11 +-
src/site/antora/modules/ROOT/pages/faq.adoc | 8 +-
.../modules/ROOT/pages/manual/api-separation.adoc | 233 ---------------
src/site/antora/modules/ROOT/pages/manual/api.adoc | 215 +++-----------
.../modules/ROOT/pages/manual/appenders.adoc | 10 +-
.../modules/ROOT/pages/manual/architecture.adoc | 12 +-
.../modules/ROOT/pages/manual/configuration.adoc | 2 +-
.../modules/ROOT/pages/manual/customloglevels.adoc | 220 --------------
.../modules/ROOT/pages/manual/eventlogging.adoc | 251 ----------------
.../modules/ROOT/pages/manual/extending.adoc | 2 +-
.../modules/ROOT/pages/manual/flowtracing.adoc | 213 --------------
.../modules/ROOT/pages/manual/garbagefree.adoc | 4 +-
.../antora/modules/ROOT/pages/manual/layouts.adoc | 6 +-
.../modules/ROOT/pages/manual/logbuilder.adoc | 78 -----
.../antora/modules/ROOT/pages/manual/lookups.adoc | 4 +-
.../antora/modules/ROOT/pages/manual/markers.adoc | 157 ----------
.../antora/modules/ROOT/pages/manual/messages.adoc | 326 ---------------------
.../modules/ROOT/pages/manual/migration.adoc | 2 +-
.../modules/ROOT/pages/manual/performance.adoc | 4 +-
.../modules/ROOT/pages/manual/resource-logger.adoc | 88 ------
.../modules/ROOT/pages/manual/scoped-context.adoc | 116 --------
.../ROOT/pages/manual/systemproperties.adoc | 6 +-
.../modules/ROOT/pages/manual/thread-context.adoc | 238 ---------------
.../modules/ROOT/partials/log4j-features.adoc | 2 +-
.../ROOT/partials/manual/async-drawbacks.adoc | 4 +-
.../manual/systemproperties/properties-async.adoc | 4 +-
.../properties-configuration-factory.adoc | 2 +-
.../properties-garbage-collection.adoc | 4 +-
.../systemproperties/properties-log-event.adoc | 6 +-
.../properties-logger-context.adoc | 2 +-
.../systemproperties/properties-message.adoc | 6 +-
.../properties-thread-context.adoc | 4 +-
.../partials/properties-garbage-collection.adoc | 6 +-
.../ROOT/partials/properties-thread-context.adoc | 4 +-
36 files changed, 89 insertions(+), 2163 deletions(-)
diff --git a/src/site/antora/antora.tmpl.yml b/src/site/antora/antora.tmpl.yml
index 65e7d8d1a4..648a8109a9 100644
--- a/src/site/antora/antora.tmpl.yml
+++ b/src/site/antora/antora.tmpl.yml
@@ -46,6 +46,7 @@ asciidoc:
java-target-version: "${maven.compiler.target}"
java-compiler-version: "${minimalJavaBuildVersion}"
logging-services-url: "https://logging.apache.org"
+ log4j2-url: "https://logging.apache.org/log4j/2.x"
lmax-disruptor-url: "https://lmax-exchange.github.io/disruptor"
# Dependency versions
commons-logging-version: "${site-commons-logging.version}"
diff --git a/src/site/antora/antora.yml b/src/site/antora/antora.yml
index ce99130556..5cf5bb97e8 100644
--- a/src/site/antora/antora.yml
+++ b/src/site/antora/antora.yml
@@ -46,6 +46,7 @@ asciidoc:
java-target-version: "17"
java-compiler-version: "[17,18)"
logging-services-url: "https://logging.apache.org"
+ log4j2-url: "https://logging.apache.org/log4j/2.x"
lmax-disruptor-url: "https://lmax-exchange.github.io/disruptor"
# Dependency versions
commons-logging-version: "1.4.0"
diff --git a/src/site/antora/modules/ROOT/nav.adoc b/src/site/antora/modules/ROOT/nav.adoc
index 026d4b60b7..61c01232cb 100644
--- a/src/site/antora/modules/ROOT/nav.adoc
+++ b/src/site/antora/modules/ROOT/nav.adoc
@@ -31,15 +31,7 @@
* xref:manual/installation.adoc[]
* xref:manual/architecture.adoc[]
* xref:manual/migration.adoc[]
-* xref:manual/api.adoc[]
-** xref:manual/logbuilder.adoc[]
-** xref:manual/flowtracing.adoc[]
-** xref:manual/markers.adoc[]
-** xref:manual/eventlogging.adoc[]
-** xref:manual/messages.adoc[]
-** xref:manual/thread-context.adoc[]
-** xref:manual/scoped-context.adoc[]
-** xref:manual/resource-logger.adoc[]
+* xref:manual/api.adoc[API]
* xref:manual/configuration.adoc[]
* xref:manual/usage.adoc[]
* xref:manual/cloud.adoc[]
@@ -51,7 +43,6 @@
* xref:manual/extending.adoc[]
* xref:manual/plugins.adoc[]
* xref:manual/customconfig.adoc[]
-* xref:manual/customloglevels.adoc[]
* xref:manual/jmx.adoc[]
* xref:manual/logsep.adoc[]
* xref:manual/performance.adoc[]
diff --git a/src/site/antora/modules/ROOT/pages/faq.adoc b/src/site/antora/modules/ROOT/pages/faq.adoc
index 9e5ee833b2..dcbdf2bfb0 100644
--- a/src/site/antora/modules/ROOT/pages/faq.adoc
+++ b/src/site/antora/modules/ROOT/pages/faq.adoc
@@ -67,7 +67,7 @@ Normally there is no need to do this manually.
Each `LoggerContext` registers a shutdown hook that takes care of releasing resources when the JVM exits, unless the `log4j.shutdownHookEnabled` system property is set to `false`.
Likewise, {logging-services-url}/log4j/jakarta[Web applications] replace the shutdown hook with their own resource management mechanisms.
That is, they clean up necessary resources when the web application is stopped.
-However, if you need to manually shut down Log4j, you can use one of the `shutdown()` methods of link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#shutdown()[`LogManager`].
+However, if you need to manually shut down Log4j, you can use one of the `shutdown()` methods of {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#shutdown()[`LogManager`].
[#reconfig_level_from_code]
== How do I set a logger level programmatically?
@@ -153,10 +153,10 @@ There are several advantages to using Log4j API:
* SLF4J forces your application to log ``String``s.
Log4j API supports logging any `CharSequence` if you want to log text, but also supports logging any `Object` as is.
It is the responsibility of the logging _implementation_ to handle this object, and we consider it a design mistake to limit applications to logging ``String``s.
-* Log4j API offers support for logging xref:manual/messages.adoc[`Message` objects].
+* Log4j API offers support for logging {log4j2-url}/manual/messages.adoc[`Message` objects].
Messages allow support for interesting and complex constructs to be passed through the logging system and be efficiently manipulated.
Users are free to create their own message types and write custom layouts, filters and lookups to manipulate them.
-* Log4j API supports xref:manual/api.adoc#LambdaSupport[lambda expressions] both in its plain and fluent API.
+* Log4j API supports {log4j2-url}/manual/api.adoc#fluent-api[lambda expressions] both in its plain and fluent API.
* Log4j API has better support for xref:manual/garbagefree.adoc[garbage-free logging]: it avoids creating `vararg` arrays and avoids creating ``String``s when logging ``CharSequence``s.
[#gc-free-slf4j]
@@ -201,7 +201,7 @@ The problem with custom logger wrappers is that they have a different FQCN than
The solution is to provide the correct FQCN.
The easiest way to do this is to let Log4j generate the logger wrapper for you.
Log4j comes with a Logger wrapper generator tool.
-This tool was originally meant to support custom log levels and is documented xref:manual/customloglevels.adoc#CustomLoggers[here].
+This tool was originally meant to support custom log levels and is documented {log4j2-url}/manual/customloglevels.adoc#CustomLoggers[here].
The generated logger code will take care of the FQCN.
[#proguard-rules]
diff --git a/src/site/antora/modules/ROOT/pages/manual/api-separation.adoc b/src/site/antora/modules/ROOT/pages/manual/api-separation.adoc
deleted file mode 100644
index 51233ef907..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/api-separation.adoc
+++ /dev/null
@@ -1,233 +0,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.
-////
-= API Separation
-
-When selecting a logging library, some care must be taken in order to ensure that multiple different logging libraries are properly accounted for.
-For example, library code that you depend on may use slf4j, while other libraries may simply use java.util.logging.
-All of these can be routed to the log4j core in order to be logged.
-
-If however you want to use a different logging implementation (such as logback), it is possible to route messages from the Log4j API to logback, ensuring that your application is not tied to a specific logging framework.
-
-A typical class using the Log4j2 API looks like the following:
-
-[,java]
-----
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-public class Log4j2Test {
- private static final Logger logger = LogManager.getLogger();
-
- public Log4j2Test(){
- logger.info( "Hello World!" );
- }
-}
-----
-
-In order to use the API portion of Log4j2, we only need to provide a single dependency, log4j-api.
-Using Maven, you would add the following to your dependencies:
-
-[,xml]
-----
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-api</artifactId>
- <version>2.17.0</version>
-</dependency>
-----
-
-== Using Log4j2 API and Core
-
-Using the Log4j2 API and the implementation (Core) together means that log messages will be routed through the Log4j2 Core.
-The Log4j2 core implementation is responsible for the following (note: this is not an exhaustive list):
-
-* Configuration of the system (via an XML file for example)
-* Routing messages to Appenders
-* Opening files and other resources for logging (e.g.
-network sockets)
-
-The xref:manual/configuration.adoc[configuration] page in the manual describes the configuration format supported by the Log4j2 core implementation.
-
-To use both the API and the core implementation, you would add the following to your dependencies (assuming that you are using Maven):
-
-[,xml]
-----
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-api</artifactId>
- <version>2.17.0</version>
-</dependency>
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.17.0</version>
-</dependency>
-----
-
-Note that having two different versions of log4j-api and log4j-core on your classpath is not guaranteed to work correctly (e.g., log4j-api version 2.15 and log4j-core version 2.17 are not guaranteed to work correctly together).
-
-== Using Log4j2 API with Logback
-
-Since the Log4j2 API is generic, we can use it to send messages via SLF4J and then have Logback do the actual logging of the messages.
-This means that you can write your code tied to the Log4j2 API, but users of your code do not need to use the Log4j2 core if they are already using Logback.
-
-To switch to using Logback as your logging backend, you will need to add the following to your dependencies (assuming that you are using Maven):
-
-[,xml]
-----
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-api</artifactId>
- <version>2.17.0</version>
-</dependency>
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-to-slf4j</artifactId>
- <version>2.17.0</version>
-</dependency>
-<dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.2.10</version>
-</dependency>
-----
-
-== Using Log4j2 as an SLF4J Implementation
-
-If you don't want to depend on the Log4j2 API and instead want to use SLF4J, that is possible as well.
-Assuming that our code looks like the following:
-
-[,java]
-----
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Log4j2Test {
-
- private static final Logger logger = LoggerFactory.getLogger(Log4j2Test.class);
-
- public Log4j2Test(){
- logger.info( "Hello World!" );
- }
-}
-----
-
-We can then route the messages to Log4j2 using the log4j-slf4j-impl like the following:
-
-[,xml]
-----
-<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.7.32</version>
-</dependency>
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-slf4j-impl</artifactId>
- <version>2.17.0</version>
-</dependency>
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.17.0</version>
-</dependency>
-----
-
-Note that if we were using SLF4J 1.8 instead of 1.7, that requires us to use log4j-slf4j18-impl instead of log4j-slf4j-impl.
-
-== Using Log4j2 with JUL
-
-It is also possible to route messages that are logged using java.util.logging to Log4j2.
-Assuming that the code looks like the following:
-
-[,java]
-----
-import java.util.logging.Logger;
-
-public class Log4j2Test {
-
- private static final Logger logger = Logger.getLogger(Log4j2Test.class.getName());
-
- public Log4j2Test() {
- logger.info("Hello World!");
- }
-}
-----
-
-We can then also route these messages to the Log4j2 core by adding in the JUL bridge, and setting `-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager` on the JVM (see the documentation on xref:../log4j-jul.adoc[the JUL adapter] for more information as to how this works).
-
-In order to route these messages to Log4j2, your dependencies would look like the following:
-
-[,xml]
-----
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-jul</artifactId>
- <version>2.17.0</version>
-</dependency>
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.17.0</version>
-</dependency>
-----
-
-== Using Log4j2 as a backend for Log4j1
-
-Some software may still depend on Log4j1, and in some cases it may be infeasible to modify this software to migrate it to Log4j2.
-
-However, it may be possible to start using Log4j2 without modifying the application.
-
-Assuming that our code looks like the following:
-
-[,java]
-----
-import org.apache.log4j.Logger;
-
-public class Log4j2Test {
-
- private static final Logger logger = Logger.getLogger(Log4j2Test.class);
-
- public Log4j2Test(){
- logger.info( "Hello World!" );
- }
-}
-----
-
-we can then quickly and easily configure these messages to use Log4j2 as the logging implementation by depending on the `log4j-1.2-api` bridge, like so:
-
-[,xml]
-----
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-1.2-api</artifactId>
- <version>2.17.0</version>
-</dependency>
-<dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.17.0</version>
-</dependency>
-----
-
-There are some limitations to this, but it is expected to work for the majority of common cases.
-See the xref:manual/migration.adoc[manual page on migration] for more information on this feature.
-
-== Conclusion
-
-With the API separation that Log4j2 provides, it is possible to use multiple logging APIs and implementations in the same project.
-This allows for greater flexibility, ensuring that you are not tied to a single API or implementation.
diff --git a/src/site/antora/modules/ROOT/pages/manual/api.adoc b/src/site/antora/modules/ROOT/pages/manual/api.adoc
index 7c5b8d0154..5a0a6bc1f5 100644
--- a/src/site/antora/modules/ROOT/pages/manual/api.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/api.adoc
@@ -14,187 +14,40 @@
See the License for the specific language governing permissions and
limitations under the License.
////
-= Log4j API
-
-== Overview
-
-The Log4j 2 API provides the interface that applications should code to
-and provides the adapter components required for implementers to create
-a logging implementation. Although Log4j 2 is broken up between an API
-and an implementation, the primary purpose of doing so was not to allow
-multiple implementations, although that is certainly possible, but to
-clearly define what classes and methods are safe to use in "normal"
-application code.
-
-=== Hello World!
-
-No introduction would be complete without the customary Hello, World
-example. Here is ours. First, a Logger with the name "HelloWorld" is
-obtained from the
-link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html[`LogManager`].
-Next, the logger is used to write the "Hello, World!" message, however
-the message will be written only if the Logger is configured to allow
-informational messages.
-
-[source,java]
-----
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-public class HelloWorld {
- private static final Logger logger = LogManager.getLogger("HelloWorld");
- public static void main(String[] args) {
- logger.info("Hello, World!");
- }
-}
-----
-
-The output from the call to `logger.info()` will vary significantly
-depending on the configuration used. See the
-xref:manual/configuration.adoc[Configuration] section for more details.
-
-=== Substituting Parameters
-
-Frequently the purpose of logging is to provide information about what
-is happening in the system, which requires including information about
-the objects being manipulated. In Log4j 1.x this could be accomplished
-by doing:
-
-[source,java]
-----
-if (logger.isDebugEnabled()) {
- logger.debug("Logging in user " + user.getName() + " with birthday " + user.getBirthdayCalendar());
-}
-----
-
-Doing this repeatedly has the effect of making the code feel like it is
-more about logging than the actual task at hand. In addition, it results
-in the logging level being checked twice; once on the call to
-isDebugEnabled and once on the debug method. A better alternative would
-be:
-
-[source,java]
-----
-logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());
-----
-
-With the code above the logging level will only be checked once and the
-String construction will only occur when debug logging is enabled.
-
-=== Formatting Parameters
-
-Formatter Loggers leave formatting up to you if `toString()` is not what
-you want. To facilitate formatting, you can use the same format strings
-as Java's
-http://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax[`Formatter`].
-For example:
-
-[source,java]
-----
-public static Logger logger = LogManager.getFormatterLogger("Foo");
-
-logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());
-logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
-logger.debug("Integer.MAX_VALUE = %,d", Integer.MAX_VALUE);
-logger.debug("Long.MAX_VALUE = %,d", Long.MAX_VALUE);
-----
-To use a formatter Logger, you must call one of the `LogManager`
-link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getFormatterLogger(java.lang.Class)[`getFormatterLogger`]
-methods. The output for this example shows that `Calendar::toString` is
-verbose compared to custom formatting:
+:jboss-logging-link: https://github.com/jboss-logging/jboss-logging[JBoss Logging]
+:jcl-link: https://commons.apache.org/proper/commons-logging/[JCL (Apache Commons Logging)]
+:jpl-link: https://openjdk.org/jeps/264[JPL (Java Platform Logging)]
+:jul-link: https://docs.oracle.com/en/java/javase/{java-target-version}/core/java-logging-overview.html[JUL (Java Logging)]
+:logback-link: https://logback.qos.ch/[Logback]
+:slf4j-link: https://www.slf4j.org/[SLF4J]
-[source,java]
-----
-2012-12-12 11:56:19,633 [main] DEBUG: User John Smith with birthday java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMod [...]
-2012-12-12 11:56:19,643 [main] DEBUG: User John Smith with birthday 05 23, 1995
-2012-12-12 11:56:19,643 [main] DEBUG: Integer.MAX_VALUE = 2,147,483,647
-2012-12-12 11:56:19,643 [main] DEBUG: Long.MAX_VALUE = 9,223,372,036,854,775,807
-----
-
-=== Mixing Loggers with Formatter Loggers
-
-Formatter loggers give fine-grained control over the output format, but
-have the drawback that the correct type must be specified (for example,
-passing anything other than a decimal integer for a %d format parameter
-gives an exception).
-
-If your main usage is to use \{}-style parameters, but occasionally you
-need fine-grained control over the output format, you can use the
-`printf` method:
-
-[source,java]
-----
-public static Logger logger = LogManager.getLogger("Foo");
-
-logger.debug("Opening connection to {}...", someDataSource);
-logger.printf(Level.INFO, "Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
-----
-
-[#LambdaSupport]
-=== Java 8 lambda support for lazy logging
-
-In release 2.4, the `Logger` interface added support for lambda
-expressions. This allows client code to lazily log messages without
-explicitly checking if the requested log level is enabled. For example,
-previously you would write:
-
-[source,java]
-----
-// pre-Java 8 style optimization: explicitly check the log level
-// to make sure the expensiveOperation() method is only called if necessary
-if (logger.isTraceEnabled()) {
- logger.trace("Some long-running operation returned {}", expensiveOperation());
-}
-----
-
-With Java 8 you can achieve the same effect with a lambda expression.
-You no longer need to explicitly check the log level:
-
-[source,java]
-----
-// Java-8 style optimization: no need to explicitly check the log level:
-// the lambda expression is not evaluated if the TRACE level is not enabled
-logger.trace("Some long-running operation returned {}", () -> expensiveOperation());
-----
-
-=== Logger Names
-
-Most logging implementations use a hierarchical scheme for matching
-logger names with logging configuration. In this scheme, the logger name
-hierarchy is represented by `'.'` characters in the logger name, in a
-fashion very similar to the hierarchy used for Java package names. For
-example, `org.apache.logging.appender` and `org.apache.logging.filter`
-both have `org.apache.logging` as their parent. In most cases,
-applications name their loggers by passing the current class's name to
-`LogManager.getLogger(...)`. Because this usage is so common, Log4j 2
-provides that as the default when the logger name parameter is either
-omitted or is null. For example, in all examples below the Logger will
-have a name of `"org.apache.test.MyTest"`.
-
-[source,java]
-----
-package org.apache.test;
-
-public class MyTest {
- private static final Logger logger = LogManager.getLogger(MyTest.class);
-}
-----
-
-[source,java]
-----
-package org.apache.test;
-
-public class MyTest {
- private static final Logger logger = LogManager.getLogger(MyTest.class.getName());
-}
-----
-
-[source,java]
-----
-package org.apache.test;
+= Log4j API
-public class MyTest {
- private static final Logger logger = LogManager.getLogger();
-}
-----
+Log4j is essentially composed of a logging API called *Log4j API*, and its reference implementation called *Log4j Core*.
+
+.What is a logging API and a logging implementation?
+[%collapsible]
+====
+Logging APIs::
+A logging API is an interface your code or your dependencies directly logs against.
+It is implementation agnostic.
+Log4j API, {slf4j-link}, {jul-link}, {jcl-link}, {jpl-link} and {jboss-logging-link} are major logging APIs.
+
+Logging implementation::
+A logging implementation is only required at runtime and can be changed without the need to recompile your software.
+Log4j Core, {jul-link}, {logback-link} are the most well-known logging implementations.
+====
+
+[TIP]
+====
+Are you looking for a crash course on how to use Log4j in your application or library?
+See xref:5min.adoc[].
+You can also check out xref:manual/installation.adoc[] for the complete installation instructions.
+====
+
+Starting with version `2.24.4`, Log4j API is embraced as the target logging API for both Log4j 2 and Log4j 3.
+Hence, **Log4j 3 does not contain a Log4j API module**, but instead implements _"the"_ Log4j API developed in Log4j 2 branch.
+This ensures Log4j 2 users can safely migrate to Log4j 3 without any Log4j API compatibility concerns.
+
+{log4j2-url}/manual/api.html[Read more on Log4j API in the Log4j 2 website...]
diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
index 923d21bb35..bfbb32bbb9 100644
--- a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
@@ -771,11 +771,11 @@ list of column mapping configurations. Each column must specify a column
name. Each column can have a conversion type specified by its fully
qualified class name. By default, the conversion type is `String`. If
the configured type is assignment-compatible with
-link:../javadoc/log4j-api/org/apache/logging/log4j/util/ReadOnlyStringMap.html[`ReadOnlyStringMap`]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/util/ReadOnlyStringMap.html[`ReadOnlyStringMap`]
/
-link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap.html[`ThreadContextMap`]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap.html[`ThreadContextMap`]
or
-link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextStack.html[`ThreadContextStack`],
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextStack.html[`ThreadContextStack`],
then that column will be populated with the MDC or NDC respectively
(this is database-specific how they handle inserting a `Map` or `List`
value). If the configured type is assignment-compatible with
@@ -1081,7 +1081,7 @@ public class ConnectionFactory {
}
----
-This appender is xref:manual/messages.adoc#MapMessage[`MapMessage`]-aware.
+This appender is {log4j2-url}/manual/messages.adoc#MapMessage[`MapMessage`]-aware.
The following configuration uses no layout to indicate that the
Appender should match the keys of a `MapMessage` to the names of
@@ -1433,7 +1433,7 @@ be increased to the nearest integer multiple of 256. See the capped
collection documentation linked above for more information.
|=======================================================================
-This appender is xref:manual/messages.adoc#MapMessage[MapMessage]-aware.
+This appender is {log4j2-url}/manual/messages.adoc#MapMessage[MapMessage]-aware.
Here are a few sample configurations for the NoSQLAppender and MongoDB
provider:
diff --git a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
index 4cab5fa7b8..199ef21e46 100644
--- a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
@@ -78,7 +78,7 @@ Logger logger = LogManager.getRootLogger();
----
All other Loggers can be retrieved using the
-link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)[`LogManager.getLogger`]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)[`LogManager.getLogger`]
static method by passing the name of the desired Logger. Further
information on the Logging API can be found in the
xref:manual/api.adoc[Log4j API].
@@ -105,10 +105,10 @@ will be stopped and discarded.
=== Logger
As stated previously, Loggers are created by calling
-link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)[`LogManager.getLogger`].
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)[`LogManager.getLogger`].
The Logger itself performs no direct actions. It simply has a name and
is associated with a LoggerConfig. It extends
-link:../javadoc/log4j-api/org/apache/logging/log4j/spi/AbstractLogger.html[`AbstractLogger`]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/AbstractLogger.html[`AbstractLogger`]
and implements the required methods. As the configuration is modified
Loggers may become associated with a different LoggerConfig, thus
causing their behavior to be modified.
@@ -162,11 +162,11 @@ process the event.
==== Log Levels
LoggerConfigs will be assigned a Log
-link:../javadoc/log4j-api/org/apache/logging/log4j/Level.html[`Level`].
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/Level.html[`Level`].
The set of built-in levels includes ALL, TRACE, DEBUG, INFO, WARN, ERROR,
-FATAL, and OFF. Log4j 2 also supports xref:manual/customloglevels.adoc[custom log
+FATAL, and OFF. Log4j 2 also supports {log4j2-url}/manual/customloglevels.adoc[custom log
levels]. Another mechanism for getting more granularity is to use
-xref:manual/markers.adoc[markers] instead. The OFF and ALL
+{log4j2-url}/manual/markers.adoc[markers] instead. The OFF and ALL
levels are not intended to be used on calls to the logging API.
Specifying OFF in the configuration implies no logging events should
match while specifying ALL would mean all events match, including custom
diff --git a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
index b997b15267..9c03b6f398 100644
--- a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
@@ -1703,7 +1703,7 @@ initialization. In addition, normal logging within appenders could
create infinite recursion which Log4j will detect and cause the
recursive events to be ignored. To accomodate this need, the Log4j 2 API
includes a
-link:../javadoc/log4j-api/org/apache/logging/log4j/status/StatusLogger.html[`StatusLogger`].
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/status/StatusLogger.html[`StatusLogger`].
Components declare an instance of the StatusLogger similar to:
[source,java]
diff --git a/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc b/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
deleted file mode 100644
index 2985da9bfa..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
+++ /dev/null
@@ -1,220 +0,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.
-////
-= Custom Log Levels
-
-[[top]]
-
-[#DefiningLevelsInCode]
-== Defining Custom Log Levels in Code
-
-Log4j 2 supports custom log levels. Custom log levels can be defined in
-code or in configuration. To define a custom log level in code, use the
-`Level.forName()` method. This method creates a new level for the
-specified name. After a log level is defined you can log messages at
-this level by calling the `Logger.log()` method and passing the custom log
-level:
-
-[source,java]
-----
-// This creates the "VERBOSE" level if it does not exist yet.
-final Level VERBOSE = Level.forName("VERBOSE", 550);
-
-final Logger logger = LogManager.getLogger();
-logger.log(VERBOSE, "a verbose message"); // use the custom VERBOSE level
-
-// Create and use a new custom level "DIAG".
-logger.log(Level.forName("DIAG", 350), "a diagnostic message");
-
-// Use (don't create) the "DIAG" custom level.
-// Only do this *after* the custom level is created!
-logger.log(Level.getLevel("DIAG"), "another diagnostic message");
-
-// Using an undefined level results in an error: Level.getLevel() returns null,
-// and logger.log(null, "message") throws an exception.
-logger.log(Level.getLevel("FORGOT_TO_DEFINE"), "some message"); // throws exception!
-----
-
-When defining a custom log level, the `intLevel` parameter (550 and 350
-in the example above) determines where the custom level exists in
-relation to the standard levels built-in to Log4j 2. For reference, the
-table below shows the `intLevel` of the built-in log levels.
-
-.Standard log levels built-in to Log4j
-[cols=",>",options="header"]
-|========================
-|Standard Level |intLevel
-|OFF |0
-|FATAL |100
-|ERROR |200
-|WARN |300
-|INFO |400
-|DEBUG |500
-|TRACE |600
-|ALL |`Integer.MAX_VALUE`
-|========================
-
-[#DefiningLevelsInConfiguration]
-== Defining Custom Log Levels in Configuration
-
-Custom log levels can also be defined in configuration. This is
-convenient for using a custom level in a logger filter or an appender
-filter. Similar to defining log levels in code, a custom level must be
-defined first, before it can be used. If a logger or appender is
-configured with an undefined level, that logger or appender will be
-invalid and will not process any log events.
-
-The *CustomLevel* configuration element creates a custom level.
-Internally it calls the same `Level.forName()` method discussed above.
-
-.CustomLevel Parameters
-[cols="m,,4",options="header"]
-|===
-|Parameter Name |Type |Description
-
-|name
-|String
-|The name of the custom level. Note that level names are
-case sensitive. The convention is to use all upper-case names.
-
-|intLevel
-|integer
-|Determines where the custom level exists in relation
-to the standard levels built-in to Log4j 2 (see the table above).
-|===
-
-The following example shows a configuration that defines some custom log
-levels and uses a custom log level to filter log events sent to the
-console.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="WARN">
- <!-- Define custom levels before using them for filtering below. -->
- <CustomLevels>
- <CustomLevel name="DIAG" intLevel="350" />
- <CustomLevel name="NOTICE" intLevel="450" />
- <CustomLevel name="VERBOSE" intLevel="550" />
- </CustomLevels>
-
- <Appenders>
- <Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/>
- </Console>
- <File name="MyFile" fileName="logs/app.log">
- <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/>
- </File>
- </Appenders>
- <Loggers>
- <Root level="trace">
- <!-- Only events at DIAG level or more specific are sent to the console. -->
- <AppenderRef ref="Console" level="diag" />
- <AppenderRef ref="MyFile" level="trace" />
- </Root>
- </Loggers>
-</Configuration>
-----
-
-[#StandardLoggerInterface]
-== Convenience Methods for the Built-in Log Levels
-
-The built-in log levels have a set of convenience methods on the Logger
-interface that makes them easier to use. For example, the Logger
-interface has 24 `debug()` methods that support the DEBUG level:
-
-[source,java]
-----
-// convenience methods for the built-in DEBUG level
-debug(Marker, Message)
-debug(Marker, Message, Throwable)
-debug(Marker, Object)
-debug(Marker, Object, Throwable)
-debug(Marker, String)
-debug(Marker, String, Object...)
-debug(Marker, String, Throwable)
-debug(Message)
-debug(Message, Throwable)
-debug(Object)
-debug(Object, Throwable)
-debug(String)
-debug(String, Object...)
-debug(String, Throwable)
-// lambda support methods added in 2.4
-debug(Marker, MessageSupplier)
-debug(Marker, MessageSupplier, Throwable)
-debug(Marker, String, Supplier<?>...)
-debug(Marker, Supplier<?>)
-debug(Marker, Supplier<?>, Throwable)
-debug(MessageSupplier)
-debug(MessageSupplier, Throwable)
-debug(String, Supplier<?>...)
-debug(Supplier<?>)
-debug(Supplier<?>, Throwable)
-----
-
-Similar methods exist for the other built-in levels. Custom levels, in
-contrast, need to pass in the log level as an extra parameter.
-
-[source,java]
-----
-// need to pass the custom level as a parameter
-logger.log(VERBOSE, "a verbose message");
-logger.log(Level.forName("DIAG", 350), "another message");
-----
-
-It would be nice to have the same ease of use with custom levels, so
-that after declaring the custom VERBOSE/DIAG levels, we could use code
-like this:
-
-[source,java]
-----
-// nice to have: descriptive methods and no need to pass the level as a parameter
-logger.verbose("a verbose message");
-logger.diag("another message");
-logger.diag("java 8 lambda expression: {}", () -> someMethod());
-----
-
-The standard Logger interface cannot provide convenience methods for
-custom levels, but the next few sections introduce a code generation
-tool to create loggers that aim to make custom levels as easy to use as
-built-in levels.
-
-[#AddingOrReplacingLevels]
-== Adding or Replacing Log Levels
-
-We assume that most users want to _add_ custom level methods to the
-Logger interface, in addition to the existing `trace()`, `debug()`, `info()`,
-... methods for the built-in log levels.
-
-There is another use case, Domain Specific Language loggers, where we
-want to _replace_ the existing `trace()`, `debug()`, `info()`, ... methods
-with all-custom methods.
-
-For example, for medical devices we could have only `critical()`,
-`warning()`, and `advisory()` methods. Another example could be a game
-that has only `defcon1()`, `defcon2()`, and `defcon3()` levels.
-
-If it were possible to hide existing log levels, users could customize
-the Logger interface to match their requirements. Some people may not
-want to have a FATAL or a TRACE level, for example. They would like to
-be able to create a custom Logger that only has `debug()`, `info()`, `warn()`
-and `error()` methods.
-
-[#CustomLoggers]
-== Generating Source Code for a Custom Logger Wrapper
-
-In order to automatically generate custom logger wrappers, see the https://logging.apache.org/log4j/transform/latest/#log4j-codegen'[Apache Log4j code generator].
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/pages/manual/eventlogging.adoc b/src/site/antora/modules/ROOT/pages/manual/eventlogging.adoc
deleted file mode 100644
index f9086bb3a6..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/eventlogging.adoc
+++ /dev/null
@@ -1,251 +0,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.
-////
-= Event Logging with Log4j
-
-The `EventLogger` class provides a mechanism for logging significant events
-in an application using structured data. This approach is beneficial for
-tracking user actions, monitoring system behavior, and debugging issues.
-
-Theoretically, every `Logger` can be used to perform this kind of action;
-however, the `EventLogger` class provides a shortcut to log events with structured data
-since it allows for a static method to log events.
-
-== Advantages of Structured Logging
-
-Structured logging means events Log4j records events with detailed and structured information.
-That way, logs are easier to read and process. They provide better context and
-are also more consistent than plain text logs.
-
-== Integration with Syslog
-
-Log4j complies with Syslogs RFC5424 standard.
-This feature allows for easy integration with existing log management and monitoring systems.
-
-== Example Configuration
-
-To configure Log4j to output logs in Syslog (RFC5424) format, one needs to use the link:../javadoc/log4j-core/org/apache/logging/log4j/core/layout/StructuredDataLayout.html[`StructuredDataLayout`] layout.
-Developers can use the following configuration to log events to a local Syslog server:
-
-[source, xml]
-----
-<Appenders>
- <Syslog name="Syslog" host="localhost" port="514"> <1>
- <StructuredDataLayout complete="true" /> <2>
- </Syslog>
-</Appenders>
-
-<Loggers>
- <Logger name="MyApp" level="info" additivity="false">
- <AppenderRef ref="Syslog"/>
- </Logger>
-</Loggers>
-----
-<1> The `Syslog` appender sends logs to a local Syslog server.
-<2> The `StructuredDataLayout` layout formats logs in RFC5424 format.
-
-Of course, sending logs to a Syslog server is unnecessary.
-Developers can use the `StructuredDataLayout` layout with any other appender, such as `FileAppender` or `ConsoleAppender`.
-
-As an example, the output could look like this:
-
-[source, text]
-----
-<165>1 2024-05-16T12:34:56.789Z myapp MyApp - ID47 [transfer@12345 toAccount="123456" fromAccount="654321" amount="1000"] User 654321 has transferred 1000 to account 123456
-----
-
-== Using the `EventLogger`
-
-The `EventLogger` class provides a simple way to log structured events.
-It uses the `StructuredDataMessage` class to create structured log messages.
-
-Assume a simple application that performs funds transfers between accounts.
-This application should send a certain amount of funds from one account to another and log the event.
-
-The account class is defined as follows, with a unique ID and a balance:
-
-[source, java]
-----
-class Account {
- private String id;
- private long balance;
- // Getters and setters omitted for brevity
-}
-----
-
-The `transfer()` method transfers funds between two accounts and logs the event.
-It needs to take two accounts and the amount to transfer as parameters.
-
-Apart from the key-value pairs provided in the map of the `StructuredDataMessage,`
-the `StructuredDataMessage` also takes a unique ID, a free-form message, and a type as parameters.
-
-The free-form message is a human-readable description of the event.
-This message is good for operators who need to understand the event quickly,
-but not so much for automated processing.
-
-[source, java]
-----
-public static String transferFunds(Account toAccount, Account fromAccount, long amount) {
- toAccount.deposit(amount);
- fromAccount.withdraw(amount);
-
- // Create a unique ID for the transaction
- String confirm = UUID.randomUUID().toString();
-
- String freeFormMessage = "User " + fromAccount.getId() + " has transferred " + amount + " to account " + toAccount.getId(); <1>
-
- // Create the StructuredDataMessage
- StructuredDataMessage msg = new StructuredDataMessage(confirm, freeFormMessage, "transfer"); <2>
- msg.put("toAccount", toAccount.getId()); <3>
- msg.put("fromAccount", fromAccount.getId());
- msg.put("amount", amount);
-
- // Log the event
- EventLogger.logEvent(msg); <4>
-
- return confirm;
-}
-----
-<1> The free-form message is a human-readable description of the event.
-<2> The `StructuredDataMessage` constructor takes an ID, the free-form message, and a type.
-<3> Developers can add key-value pairs to the message.
-<4> The `EventLogger` logs the event.
-
-That way, the `transferFunds()` method logs the event with structured data
-by using the `EventLogger`.
-
-== Web Application Example
-
-In a web application, developers can use a servlet filter to populate the
-`ThreadContext` map with data related to the request.
-
-The following example demonstrates how a `Filter` could investigate the request
-and populate the `ThreadContext` map with data such as the user's IP address,
-the user's login ID, the server's hostname, the product name, the locale, and the timezone.
-
-[source, java]
-----
-import org.apache.logging.log4j.ThreadContext;
-import org.apache.commons.lang.time.DateUtils;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-import java.io.IOException;
-import java.util.TimeZone;
-
-public class RequestFilter implements Filter {
- private FilterConfig filterConfig;
- private static String TZ_NAME = "timezoneOffset";
-
- // Other methods ommitted for brevity
-
- /**
- * 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;
-
- ThreadContext.put("ipAddress", request.getRemoteAddr()); <1>
-
- HttpSession session = request.getSession(false);
- if (session != null) {
- // Assuming, an authentication filter has already populated the loginId in the session
- String loginId = (String)session.getAttribute("loginId");
- if (loginId != null) {
- ThreadContext.put("loginId", loginId);
- }
- }
-
- ThreadContext.put("hostname", servletRequest.getServerName());
- ThreadContext.put("productName", filterConfig.getInitParameter("ProductName"));
- ThreadContext.put("locale", servletRequest.getLocale().getDisplayName());
- ThreadContext.put("timezone", TimeZone.getDefault().getDisplayName());
-
- filterChain.doFilter(servletRequest, servletResponse);
- ThreadContext.clear();
- }
-}
-----
-<1> The `doFilter()` method populates the `ThreadContext` map with data related to the request.
-
-The `Filter` needs to be registered in your `web.xml` file:
-
-[source, xml]
-----
-<filter>
- <filter-name>RequestFilter</filter-name>
- <filter-class>com.example.RequestFilter</filter-class>
- <init-param>
- <param-name>ProductName</param-name>
- <param-value>YourProductName</param-value>
- </init-param>
-</filter>
-<filter-mapping>
- <filter-name>RequestFilter</filter-name>
- <url-pattern>/*</url-pattern> <1>
-</filter-mapping>
-----
-<1> The `RequestFilter` is mapped to all requests.
-
-Eventually, a `Servlet` or any other related class, such as a Spring Controller, can be used to log events with structured data.
-The following example uses a `Servlet` to call the `EventLogger` and log a user action.
-
-[source, java]
-----
-import javax.servlet.*;
-import javax.servlet.http.*;
-import java.io.IOException;
-
-public class UserActionServlet extends HttpServlet {
-
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String userId = request.getParameter("userId");
- String action = request.getParameter("action");
- String details = request.getParameter("details");
-
- // Perform and log the user action
- String message = "User " + userId + " performed action: " + action;
- StructuredDataMessage msg = new StructuredDataMessage(UUID.randomUUID().toString(), message, "userAction"); <1>
- msg.put("userId", userId);
- msg.put("action", action);
- msg.put("details", details);
-
- // Log the event
- EventLogger.logEvent(msg);
-
- // Respond to the client
- response.getWriter().write("Action logged successfully");
- }
-}
-----
-<1> `userAction` is the name of the current transaction
-
-That way, not only the data provided to the `EventLogger` is used, but also all the
-data populated in the `ThreadContext` map is included in the log message.
-
-== Benefits of Structured Logging
-
-1. **Improved Readability and Context:**
-Structured logs include detailed information, making them easier to understand and analyze.
-2. **Better for Automated Processing:**
-Structured logs are easily parsed by existing log management tools.
-3. **Consistency:**
-Structured logging enforces a consistent format, helping to identify patterns in logs.
-4. **Performance Optimization:**
-Structured messages are - as all messages - only constructed when necessary, keeping overhead low.
-
diff --git a/src/site/antora/modules/ROOT/pages/manual/extending.adoc b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
index ad74b093dc..d356d86190 100644
--- a/src/site/antora/modules/ROOT/pages/manual/extending.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
@@ -606,7 +606,7 @@ implementation can be installed by setting system property `log4j2.threadContext
to the fully qualified class name of the class implementing the `ThreadContextMap`
interface. By also implementing the `ReadOnlyThreadContextMap` interface, your custom
`ThreadContextMap` implementation will be accessible to applications via the
-link:../javadoc/log4j-api/org/apache/logging/log4j/ThreadContext.html#getThreadContextMap()[`ThreadContext::getThreadContextMap`]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/ThreadContext.html#getThreadContextMap()[`ThreadContext::getThreadContextMap`]
method.
[#Custom_Plugins]
diff --git a/src/site/antora/modules/ROOT/pages/manual/flowtracing.adoc b/src/site/antora/modules/ROOT/pages/manual/flowtracing.adoc
deleted file mode 100644
index 10070e76aa..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/flowtracing.adoc
+++ /dev/null
@@ -1,213 +0,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.
-////
-= Flow Tracing
-
-Flow tracing in Log4j is an advanced logging technique designed to enhance
-the visibility of application processes. With this technique, developers can track
-data flow through their application using unique methods that log entry
-and exit points within the code.
-
-These methods are:
-
-* `traceEntry()` (Deprecated `entry()`)
-* `traceExit()` (Deprecated: `exit()`)
-* `throwing()`
-* `catching()`
-
-With these methods, we can investigate environments where traditional debugging is not possible,
-such as in production or during live application monitoring.
-Furthermore, new developers can be educated on the application's behavior by examining the logs.
-
-Flow tracing offers a structured approach to all this.
-
-== Flow Tracing Methods
-
-The methods often used are `traceEntry()` and `traceExit()`.
-As the name suggests, the "entry" method is used at the beginning and the "exit" method at the end of a method.
-
-[source, java]
-----
-public void someMethod() {
- logger.traceEntry(); <1>
- // method body
- logger.traceExit(); <2>
-}
-----
-<1> The `entry()` method is called at the beginning of the method.
-<2> The `exit()` method is called at the end of the method.
-
-Developers can call both `traceEntry()` and `traceExit()` methods with or without parameters.
-In the case of `traceEntry()`, it makes sense to pass the method parameters on as arguments.
-
-[source, java]
-----
-public void someMethod(String param) {
- logger.traceEntry(param); <1>
- // method body
- logger.traceExit(); <2>
-}
-----
-<1> The `traceEntry()` method is called at the beginning of the method.
-<2> The `traceExit()` method is called at the end of the method.
-
-The `traceEntry()` also supports messages.
-
-[source, java]
-----
-public void someMethod(String[] text) {
- logger.traceEntry(new JsonMessage(text)); <1>
- // method body
-}
-----
-<1> Using the `JsonMessage` class to log the `text` parameter.
-
-Very similar, it is possible to use `traceExit()` with methods that return a value.
-
-[source, java]
-----
-public String someMethod() {
- String result = "Hello";
- // method body
- return logger.traceExit(result); <1>
-}
-----
-<1> The `traceExit()` method can also return a value.
-
-Developers can use the `catching()` and `throwing()` methods to work with exceptions.
-
-The following code shows the `catching()` method. It will be called
-inside the `catch` block of a try-catch statement.
-
-The `catching()` method can be used by an application when it catches an
-Exception that it will not rethrow, either explicitly or attached
-to another Exception. The generated logging event will have an `ERROR` level.
-
-[source, java]
-----
-public void someMethod() {
- try {
- // Let's assume an exception is thrown here
- String msg = messages[messages.length];
- } catch (Exception ex) {
- logger.catching(ex); <1>
- }
-}
-----
-<1> The `catching()` method logs exceptions that are caught and not rethrown.
-
-The `throwing()` method is used to log exceptions that are thrown and not caught.
-The code shows how to use the `throwing()` method- like `catching()`, which will be called
-inside the `catch` block of a try-catch statement.
-
-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 ensure that proper diagnostics are available if needed.
-The generated logging event will have an `ERROR` level.
-
-[source, java]
-----
-public void someMethod() {
- try {
- // Let's assume an exception is thrown here
- String msg = messages[messages.length];
- } catch (Exception ex) {
- logger.throwing(ex); <1>
- }
-}
-----
-<1> The `throwing()` method logs exceptions that are thrown and not caught.
-
-== Differences in flow tracing methods
-
-Flow tracing methods have specific markers assigned and logs with a level of `TRACE`.
-It's also noteworthy that all messages begin with "event".
-
-The table below shows the methods and their unique features.
-
-[cols="3,3,3", options="header"]
-|===
-| Method Name | Marker Name | Special Features
-
-| `traceEntry()`
-| `ENTER`, `FLOW`
-| Can take a format string and a variable list of parameters.
-
-| `entry()`
-| `ENTER`, `FLOW`
-| DEPRECATED. Accepts 0 to 4 parameters
-
-| `traceExit()`
-| `EXIT`, `FLOW`
-| Handles return values differently based on the method signature.
-
-| `exit()`
-| `EXIT`, `FLOW`
-| DEPRECATED. Can be called with or without parameters.
-
-| `throwing()`
-| `THROWING`, `EXCEPTION`
-| Typically used when an application throws an exception that is unlikely to be handled, such as a RuntimeException.
-
-| `catching()`
-| `CATCHING`, `EXCEPTION`
-| Used when catching exceptions that are not rethrown; logs with ERROR level.
-
-|===
-
-== Flow Tracing Example Configuration
-
-The following example demonstrates how to configure Log4j to use flow tracing.
-Note: While developers should prefer the `JsonTemplateLayout` in production, this example uses `PatternLayout` for simplicity.
-
-Two appenders are defined: `Console` and `File`.
-
-The `Console` appender outputs logs to `SYSTEM_OUT`, typically the console.
-It includes a `ThresholdFilter` set to only accept messages at the `ERROR` level or above.
-Less severe messages are filtered.
-
-Similarly, the File appender directs logs to a file named `target/test.log`.
-The appenders configuration will create a new file for every application run.
-
-Both appenders use the already mentioned `PatternLayout`, which includes detailed information such as time, log level, class name, line number, and method name.
-
-Finally, in the Loggers section, the Root logger is set to a `TRACE` level, which is necessary to see flow tracing in action.
-The Root logger references the File appender, directing its output to the configured file.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration>
- <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>
-----
-
-By changing the Root logger's level to `DEBUG`, developers can reduce the amount of output.
diff --git a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
index c39d36810f..81e432d013 100644
--- a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
@@ -264,7 +264,7 @@ Logging more than 10 parameters creates https://docs.oracle.com/javase/8/docs/te
When a message parameter contains an unknown type by the layout, it will encode by calling `toString()` on these objects.
Most objects don't have garbage-free `toString()` methods.
-Objects themselves can implement their own garbage-free encoders by either extending from https://docs.oracle.com/javase/8/docs/api/java/lang/CharSequence.html[Java's `CharSequence`] or link:../javadoc/log4j-api/org/apache/logging/log4j/util/StringBuilderFormattable.html[Log4j's `StringBuilderFormattable`].
+Objects themselves can implement their own garbage-free encoders by either extending from https://docs.oracle.com/javase/8/docs/api/java/lang/CharSequence.html[Java's `CharSequence`] or {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/util/StringBuilderFormattable.html[Log4j's `StringBuilderFormattable`].
[#codeImpact]
=== Avoiding autoboxing
@@ -310,5 +310,5 @@ LOGGER.debug(() -> callExpensiveMethod());
----
+
is garbage-free.
-* The link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#traceEntry()[`traceEntry()`] and link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#traceExit()[`traceExit()`] methods create temporary objects.
+* The {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/Logger.html#traceEntry()[`traceEntry()`] and {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/Logger.html#traceExit()[`traceExit()`] methods create temporary objects.
* Time calculations are not garbage-free when the `log4j2.usePreciseClock` system property (defaults to `false`) is set to `true`.
diff --git a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
index 27a560c57c..63a27489bf 100644
--- a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
@@ -903,7 +903,7 @@ The STYLE value can be one of:
*map*\{key} +
*MAP*\{key}
|Outputs the entries in a
-link:../javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[MapMessage],
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[MapMessage],
if one is present in the event. The `K` conversion character can be
followed by the key for the map placed between braces, as in
`%K\{clientNumber}` where `clientNumber` is the key. The value in the
@@ -1295,7 +1295,7 @@ value pair set is output using a format {key1=val1, key2=val2}. The
key/value pairs will be printed in sorted order.
See the
-link:../javadoc/log4j-api/org/apache/logging/log4j/ThreadContext.html[ThreadContext]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/ThreadContext.html[ThreadContext]
class for more details.
|[[PatternUUID]] *u*{"RANDOM" \| "TIME"} +
@@ -1684,7 +1684,7 @@ resulting from evaluation of the pattern - garbage-free since 2.8
|%K\{key}, %map\{key}, %MAP\{key}
|Outputs the entries in a
-link:../javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[MapMessage],
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[MapMessage],
if one is present in the event - garbage-free since 2.8.
|%m, %msg, %message
diff --git a/src/site/antora/modules/ROOT/pages/manual/logbuilder.adoc b/src/site/antora/modules/ROOT/pages/manual/logbuilder.adoc
deleted file mode 100644
index f6b93f158a..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/logbuilder.adoc
+++ /dev/null
@@ -1,78 +0,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.
-////
-
-= Log Builder
-
-Log4j has traditionally been used with logging statements like
-[source,java]
-----
-logger.error("Unable to process request due to {}", code, exception);
-----
-
-This has resulted in some confusion as to whether the exception should be a parameter to the message or
-if Log4j should handle it as a throwable. In order to make logging clearer a builder pattern has been
-added to the API. Using the builder syntax the above would be handled as:
-[source,java]
-----
-logger.atError().withThrowable(exception).log("Unable to process request due to {}", code);
-----
-
-With this syntax it is clear that the exception is to be treated as a Throwable by Log4j.
-
-The Logger class now returns a LogBuilder when any of the atTrace, atDebug, atInfo, atWarn, atError,
-atFatal, always, or atLevel(Level) methods are called. The logBuilder then allows a Marker, Throwable,
-and/or location to be added to the event before it is logged. A call to the log method always causes the
-log event to be finalized and sent.
-
-A logging statement with a Marker, Throwable, and location would look like:
-[source,java]
-----
-logger.atInfo().withMarker(marker).withLocation().withThrowable(exception).log("Login for user {} failed", userId);
-----
-Providing the location method on the LogBuilder provides two distinct advantages:
-
-1. Logging wrappers can use it to provide the location information to be used by Log4j.</li>
-2. The overhead of capturing location information when using the location method with no
-parameters is much better than having to calculate the location information when it is needed. Log4j
-can simply ask for the stack trace entry at a fixed index instead of having to walk the stack trace
-to determine the calling class. Of course, if the location information will not be used by the layout
-this will result in slower performance.</li>
-
-== Location Performance
-
-The table below shows some of the results from the FileAppenderBenchmark and FileAppenderWithLocationBenchmark
-classes in the log4j-perf-test project when configured to use 4 threads. The results show that lazily including
-the location information is about 8 times slower than not including location information. While using the
-withLocation method of LogBuilder is about 3 times faster than lazily calculating the location information
-it is still about 2.5 times slower than not including location information.
-
-The tests were run on a 2018 MacBook Pro with a 2.9 GHz Intel Core i9 processor with 6 cores, 32 GB of memory
-and 1 TB of SSD storage on Java 11 using Log4j 2.13.0 and Logback 1.2.3.
-image:LocationPerf.png[Location Performance]
-
-|===
-|Test|Print Location Info|No Location Info Printed
-
-|Log4j2 File| 191,509.724 ± 11339.978 ops/s| 1,407,329.130 ± 22595.997 ops/s
-|Log4j2 Log Builder withLocation()|469,200.684 ± 50025.985 ops/s|577,127.463 ± 11464.342 ops/s
-|Logback File|159,116.538 ± 1884.969 ops/s|1,240,438.384 ± 76619.873 ops/s
-|===
-As expected, when using LogBuilder with a call to the withLocation() method logging is much faster when
-location information is used in the output but significantly slower when it is not.
-
-Note: Running the tests at various times provides varying results. Although some results have been as much
-as 10% higher all results are generally affected similarly so the comparisons between them stay the same.
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
index 6eb03e8b08..8ed6754eff 100644
--- a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
@@ -441,7 +441,7 @@ The first item simply means that the MapLookup is used to substitute
properties that are defined in the configuration file. These variables
are specified without a prefix - e.g. `$\{name}`. The second usage allows
a value from the current
-link:../javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[`MapMessage`],
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[`MapMessage`],
if one is part of the current log event, to be substituted. In the
example below the RoutingAppender will use a different
RollingFileAppender for each unique value of the key named "type" in the
@@ -547,7 +547,7 @@ values it will also return the name portion of the id (not including the
enterprise number) and the type field. The main difference between the
example below and the example for MapMessage is that the "type" is an
attribute of the
-link:../javadoc/log4j-api/org/apache/logging/log4j/message/StructuredDataMessage.html[StructuredDataMessage]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/StructuredDataMessage.html[StructuredDataMessage]
while "type" would have to be an item in the Map in a MapMessage.
[source,xml]
diff --git a/src/site/antora/modules/ROOT/pages/manual/markers.adoc b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
deleted file mode 100644
index ae863186eb..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/markers.adoc
+++ /dev/null
@@ -1,157 +0,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.
-////
-= Markers
-
-Markers allow to _tag_ log statements with a
-link:../javadoc/log4j-api/org/apache/logging/log4j/Marker.html[`Marker`]
-object, labeling them as belonging to a specific type.
-For example, developers can use markers to tag log statements related to a particular subsystem or functionality.
-
-By using markers, it is possible to filter log statements based on the `Marker`
-and display only those log statements that are of interest, such as those
-related to XML processing or SQL queries.
-
-Markers offer more fine-grained control over log filtering beyond log levels or package names.
-
-[#create]
-== Creating Markers
-
-[#simple-markers]
-=== Simple markers
-
-To create a `Marker`, create a field in your class using the `MarkerManager.getMarker()` method:
-
-[source, java, indent=0]
-----
-include::example$manual/markers/MarkerExample.java[tag=create-marker]
-----
-
-Since a `Marker` is reusable across multiple log statements, storing it in a `static final` field makes it a constant.
-Once created, use it as the first argument in the log statement:
-
-[source, java, indent=0]
-----
-include::example$manual/markers/MarkerExample.java[tag=use-marker]
-----
-
-If you use the <<example-configuration,configuration example below>>, one can see the following log statement on your console:
-
-[source, text]
-----
-include::example$manual/markers/marker-filtering.log[tag=use-marker]
-----
-
-[#hierarchy]
-=== Parent and child markers
-
-A marker can have zero or more parent markers, allowing for a hierarchy of markers.
-To create such a hierarchy, you must use the `addParents()` method on the `Marker` object after you make the child marker.
-
-[source, java, indent=0]
-----
-include::example$manual/markers/MarkerExample.java[tag=create-marker-parent]
-----
-
-Child markers do not differ from simple markers; one must pass them on as the first argument of a logging call.
-
-[source, java, indent=0]
-----
-include::example$manual/markers/MarkerExample.java[tag=use-marker-parent]
-----
-
-Messages marked with children's markers behave as if they were both marked with the children's marker and all its parents.
-If you use the <<example-configuration,configuration example below>>, you'll see the following log statement on your console:
-
-[source, text]
-----
-include::example$manual/markers/marker-filtering.log[tag=use-marker-parent]
-----
-
-[#configuring-log4j]
-== Configuring filtering
-
-Developers can use markers to filter the log statements delivered to log files.
-Marker processing is supported at least by
-https://logback.qos.ch/manual/filters.html#TurboFilter[Logback]
-and the Log4j Core logging backends.
-We will discuss only the configuration of the latter.
-
-To filter messages by marker, you need to add
-xref:manual/filters.adoc#MarkerFilter[`MarkerFilter`]
-to your configuration file.
-For example, one can use the snippet below to redirect all SQL-related logs to the `SQL_LOG` appender:
-
-[[example-configuration]]
-[tabs]
-====
-XML::
-+
-[source, xml]
-----
-include::example$manual/markers/log4j2.xml[tag=logger]
-----
-
-JSON::
-+
-[source, json]
-----
-include::example$manual/markers/log4j2.json[tag=logger]
-----
-
-YAML::
-+
-[source, yaml]
-----
-include::example$manual/markers/log4j2.yaml[tag=logger]
-----
-
-Java properties::
-+
-[source, properties]
-----
-include::example$manual/markers/log4j2.properties[tag=logger]
-----
-====
-
-<1> Match all messages from `example` package from all levels
-<2> Only allow messages marker with `SQL` or one of its children to be sent to the `SQL_LOG` appender.
-
-[#pitfalls]
-== Pitfalls
-
-It is important to note that marker names must be unique, as Log4j registers them permanently by name.
-Developers should avoid generic marker names, as they may conflict with
-those provided by third parties. Except, of course, if the user is aware of the implications.
-
-While it is possible to add or remove parent markers dynamically through the `setParents()` method,
-it is generally advisable to set the parents when the marker is created for efficiency and performance reasons.
-
-It is also worth noting that markers without parents are more efficient to evaluate
-than markers with multiple parents. It is generally a good idea to avoid
-complex hierarchies of markers where possible.
-
-[#complete-example]
-== Complete example
-
-To try the examples on this page:
-
-* add
-{antora-examples-url}/manual/markers/MarkerExample.java[MarkerExample.java]
-to the `src/main/java/example` folder of your project,
-* add
-{antora-examples-url}/manual/markers/log4j2.xml[log4j2.xml]
-to the `src/main/resources` folder of your project.
diff --git a/src/site/antora/modules/ROOT/pages/manual/messages.adoc b/src/site/antora/modules/ROOT/pages/manual/messages.adoc
deleted file mode 100644
index 541a117c12..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/messages.adoc
+++ /dev/null
@@ -1,326 +0,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.
-////
-= 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:
- throw new UnsupportedOperationException();
- }
- }
-
- 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:../javadoc/log4j-api/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:../javadoc/log4j-api/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 JMS Appender is configured
-with a no layout, it converts a Log4j `MapMessage` to a JMS
-`javax.jms.MapMessage`.
-* When a xref:manual/appenders.adoc#JDBCAppender[JDBC Appender] is configured
-with no layout, it converts a Log4j `MapMessage` to values in a
-SQL INSERT statement.
-* When a xref:manual/appenders.adoc#NoSQLAppenderMongoDB[MongoDB Appender] is
-configured with no layout, it converts a Log4j `MapMessage` to
-fields in a MongoDB object.
-
-[#MessageFormatMessage]
-== MessageFormatMessage
-
-link:../javadoc/log4j-api/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:../javadoc/log4j-api/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:../javadoc/log4j-api/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:../javadoc/log4j-api/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.
diff --git a/src/site/antora/modules/ROOT/pages/manual/migration.adoc b/src/site/antora/modules/ROOT/pages/manual/migration.adoc
index 202cae8d91..ee026a5eec 100644
--- a/src/site/antora/modules/ROOT/pages/manual/migration.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/migration.adoc
@@ -162,7 +162,7 @@ Equivalent functionality is provided in the Log4j 2 implementation classes, see
| Parameterized messages like `logger.info("hi {}", userName)`
| http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html[`org.apache.log4j.MDC`] and http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/NDC.html[`org.apache.log4j.NDC`]
-| xref:manual/thread-context.adoc[Thread Context]
+| {log4j2-url}/manual/thread-context.adoc[Thread Context]
|===
[#Log4j2ConfigurationFormat]
diff --git a/src/site/antora/modules/ROOT/pages/manual/performance.adoc b/src/site/antora/modules/ROOT/pages/manual/performance.adoc
index 3ea2e59eea..d328c918bf 100644
--- a/src/site/antora/modules/ROOT/pages/manual/performance.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/performance.adoc
@@ -75,7 +75,7 @@ Consider the following example:
/* BAD! */ LOGGER.info("failed for user ID `{}` and role `{}`", userId, db.findUserRoleById(userId));
----
-The database query (i.e., `db.findUserNameById(userId)`) can be a significant bottleneck if the created the log event will be discarded anyway – maybe the `INFO` level or the associated xref:manual/markers.adoc[marker] is not accepted for this package, or due to some other filtering.
+The database query (i.e., `db.findUserNameById(userId)`) can be a significant bottleneck if the created the log event will be discarded anyway – maybe the `INFO` level or the associated {log4j2-url}/manual/markers.adoc[marker] is not accepted for this package, or due to some other filtering.
* [ ] The old-school way of solving this problem is to level-guard the log statement:
+
@@ -84,7 +84,7 @@ The database query (i.e., `db.findUserNameById(userId)`) can be a significant bo
/* BAD! */ if (LOGGER.isInfoEnabled()) { LOGGER.info(...); }
----
+
-While this would work for cases where the message can be dropped due to insufficient level, this approach is still prone to other filtering cases; e.g., maybe the associated xref:manual/markers.adoc[marker] is not accepted.
+While this would work for cases where the message can be dropped due to insufficient level, this approach is still prone to other filtering cases; e.g., maybe the associated {log4j2-url}/manual/markers.adoc[marker] is not accepted.
* [x] Use ``Supplier``s to pass arguments containing computationally expensive items:
+
diff --git a/src/site/antora/modules/ROOT/pages/manual/resource-logger.adoc b/src/site/antora/modules/ROOT/pages/manual/resource-logger.adoc
deleted file mode 100644
index 674de056aa..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/resource-logger.adoc
+++ /dev/null
@@ -1,88 +0,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.
-////
-
-= Resource Logging
-The link:../log4j-api/apidocs/org/apache/logging/log4j/ResourceLogger.html[`ResourceLogger`]
-is available in Log4j API releases 2.24.0 and greater.
-
-A `ResourceLogger` is a special kind of Logger that:
-
- * is a regular class member variable that will be garbage collected along with the class instance.
- * can provide a Map of key/value pairs of data associate with the resource (the class instance)
-that will be include in every record logged from the class.
-
-The Resource Logger still uses a "regular" Logger. That Logger can be explicitly declared or encapsulated
-inside the Resource Logger.
-
-[source,java]
-----
-
- private class User {
-
- private final String loginId;
- private final String role;
- private int loginAttempts;
- private final ResourceLogger logger;
-
- public User(final String loginId, final String role) {
- this.loginId = loginId;
- this.role = role;
- logger = ResourceLogger.newBuilder()
- .withClass(this.getClass())
- .withSupplier(new UserSupplier())
- .build();
- }
-
- public void login() throws Exception {
- ++loginAttempts;
- try {
- authenticator.authenticate(loginId);
- logger.info("Login succeeded");
- } catch (Exception ex) {
- logger.warn("Failed login");
- throw ex;
- }
- }
-
-
- private class UserSupplier implements Supplier<Map<String, String>> {
-
- public Map<String, String> get() {
- Map<String, String> map = new HashMap<>();
- map.put("LoginId", loginId);
- map.put("Role", role);
- map.put("Count", Integer.toString(loginAttempts));
- return map;
- }
- }
- }
-
-----
-
-With the PatternLayout configured with a pattern of
-
-----
-%X %m%n
-----
-
-and a loginId of testUser and a role of Admin, after a successful login would result in a log message of
-
-----
-{LoginId=testUser, Role=Admin, Count=1} Login succeeded
-----
-
-Every logging call is wrapped in a ScopedContext and populated by the supplier configured on the ResourceLogger, which is called when generating every log event. This allows values, such as counters, to be updated and the log event will contain the actual value at the time the event was logged.
diff --git a/src/site/antora/modules/ROOT/pages/manual/scoped-context.adoc b/src/site/antora/modules/ROOT/pages/manual/scoped-context.adoc
deleted file mode 100644
index f80bc6f671..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/scoped-context.adoc
+++ /dev/null
@@ -1,116 +0,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.
-////
-
-= Scoped Context
-The link:../log4j-api/apidocs/org/apache/logging/log4j/ScopedContext.html[`ScopedContext`]
-is available in Log4j API releases 2.24.0 and greater.
-
-The `ScopedContext` is similar to the ThreadContextMap in that it allows key/value pairs to be included
-in many log events. However, the pairs in a `ScopedContext` are only available to
-application code and log events running within the scope of the `ScopeContext` object.
-
-The `ScopeContext` is essentially a builder that allows key/value pairs to be added to it
-prior to invoking a method. The key/value pairs are available to any code running within
-that method and will be included in all logging events as if they were part of the `ThreadContextMap`.
-
-ScopedContext is immutable. Each invocation of the `where` method returns a new ScopedContext.Instance
-with the specified key/value pair added to those defined in previous ScopedContexts.
-
-[source,java]
-----
-ScopedContext.where("id", UUID.randomUUID())
- .where("ipAddress", request.getRemoteAddr())
- .where("loginId", session.getAttribute("loginId"))
- .where("hostName", request.getServerName())
- .run(new Worker());
-
-private class Worker implements Runnable {
- private static final Logger LOGGER = LogManager.getLogger(Worker.class);
-
- public void run() {
- LOGGER.debug("Performing work");
- String loginId = ScopedContext.get("loginId");
- }
-}
-
-----
-
-The values in the ScopedContext can be any Java object. However, objects stored in the
-context Map will be converted to Strings when stored in a LogEvent. To aid in
-this Objects may implement the Renderable interface which provides a `render` method
-to format the object. By default, objects will have their toString() method called
-if they do not implement the Renderable interface.
-
-Note that in the example above `UUID.randomUUID()` returns a UUID. By default, when it is
-included in LogEvents its toString() method will be used.
-
-== Thread Support
-
-ScopedContext provides support for passing the ScopedContext and the ThreadContext to
-child threads by way of an ExecutorService. For example, the following will create a
-ScopedContext and pass it to a child thread.
-
-[source,java]
-----
-BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(5);
-ExecutorService executorService = new ThreadPoolExecutor(1, 2, 30, TimeUnit.SECONDS, workQueue);
-Future<?> future = ScopedContext.where("id", UUID.randomUUID())
- .where("ipAddress", request.getRemoteAddr())
- .where("loginId", session.getAttribute("loginId"))
- .where("hostName", request.getServerName())
- .run(executorService, new Worker());
-try {
- future.get();
-} catch (ExecutionException ex) {
- logger.warn("Exception in worker thread: {}", ex.getMessage());
-}
-
-private class Worker implements Runnable {
- private static final Logger LOGGER = LogManager.getLogger(Worker.class);
-
- public void run() {
- LOGGER.debug("Performing work");
- String loginId = ScopedContext.get("loginId");
- }
-}
-
-----
-
-ScopeContext also supports call methods in addition to run methods so the called functions can
-directly return values.
-
-== Nested ScopedContexts
-
-ScopedContexts may be nested. Becuase ScopedContexts are immutable the `where` method may
-be called on the current ScopedContext from within the run or call methods to append new
-key/value pairs. In addition, when passing a single key/value pair the run or call method
-may be combined with a where method as shown below.
-
-
-[source,java]
-----
- ScopedContext.runWhere("key1", "value1", () -> {
- assertThat(ScopedContext.get("key1"), equalTo("value1"));
- ScopedContext.where("key2", "value2").run(() -> {
- assertThat(ScopedContext.get("key1"), equalTo("value1"));
- assertThat(ScopedContext.get("key2"), equalTo("value2"));
- });
- });
-
-----
-
-ScopedContexts ALWAYS inherit the key/value pairs from their parent scope. key/value pairs may be removed from the context by passing a null value with the key. Note that where methods that accept a Map MUST NOT include null keys or values in the map.
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc b/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
index 19bb209b5f..3ffbb3dbc8 100644
--- a/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/systemproperties.adoc
@@ -130,7 +130,7 @@ The
link:../javadoc/log4j-core/org/apache/logging/log4j/core/LoggerContext.html[LoggerContext]
is one of the principal Log4j components (see
xref:manual/architecture.adoc[]), which determines among other things, the way
-link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[Logger]s are created.
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/Logger.html[Logger]s are created.
It can be customized using these properties:
@@ -154,7 +154,7 @@ include::partial$manual/systemproperties/properties-configuration-factory.adoc[l
=== Log messages
The way Log4j builds
-link:../javadoc/log4j-api/org/apache/logging/log4j/message/Message.html[Message]s can be customized using these properties:
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/Message.html[Message]s can be customized using these properties:
include::partial$manual/systemproperties/properties-message.adoc[leveloffset=+2]
@@ -251,7 +251,7 @@ If a property is not defined in a logger context specific environment, the corre
=== Global environment
The global environment delegates property resolution to the Log4j 2 API
-link:../javadoc/log4j-api/org/apache/logging/log4j/util/PropertiesUtil.html[PropertiesUtil]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/util/PropertiesUtil.html[PropertiesUtil]
service (see
link:../../2.x/manual/systemproperties.adoc#property-sources[Log4j 2 API documentation]).
diff --git a/src/site/antora/modules/ROOT/pages/manual/thread-context.adoc b/src/site/antora/modules/ROOT/pages/manual/thread-context.adoc
deleted file mode 100644
index 47430deace..0000000000
--- a/src/site/antora/modules/ROOT/pages/manual/thread-context.adoc
+++ /dev/null
@@ -1,238 +0,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.
-////
-
-= Thread Context
-
-Log4j introduced the concept of the Mapped Diagnostic Context or MDC. It
-has been documented and discussed in numerous places including
-https://veerasundar.com/blog/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`]
-(see the Configuration section). 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:../javadoc/log4j-api/org/apache/logging/log4j/ThreadContext.html[`ThreadContext`]
-class are static.
-
-=== Configuration
-
-* Set the system property `log4j2.disableThreadContextMap` to `true` to disable the Thread Context Map.
-* Set the system property `log4j2.disableThreadContextStack` to `true` to disable the Thread Context Stack.
-* Set the system property `log4j2.disableThreadContext` to `true` to disable both the Thread Context Map and Stack.
-* Set the system property `log4j2.isThreadContextMapInheritable` to `true` to enable child threads to inherit the Thread
-Context Map.
-
-== Including the ThreadContext when writing logs
-
-The
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/layout/PatternLayout.html[`PatternLayout`]
-provides mechanisms to print the contents of the
-link:../javadoc/log4j-api/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 xref:manual/extending.adoc#Custom_ContextDataProvider[extending
-Log4j] for details.
diff --git a/src/site/antora/modules/ROOT/partials/log4j-features.adoc b/src/site/antora/modules/ROOT/partials/log4j-features.adoc
index f7289e93fe..e53dd94327 100644
--- a/src/site/antora/modules/ROOT/partials/log4j-features.adoc
+++ b/src/site/antora/modules/ROOT/partials/log4j-features.adoc
@@ -24,7 +24,7 @@ Log4j bundles a rich set of components to assist various use cases.
API separation::
The API for Log4j (i.e., `log4j-api`) is separate from the implementation (i.e., `log4j-core`), making it straightforward for application developers which classes and methods to use while ensuring forward compatibility.
-(See xref:manual/api-separation.adoc[API Separation] for details.)
+(See xref:manual/api.adoc[API Separation] for details.)
The Log4j API also provides the most feature-rich logging facade in the market; support for various `Message` types (such as `Object` or `Map`) besides plain `String`, lambda expressions, parametrized logging, markers, levels, diagnostic contexts (aka. MDC/NDC), etc.
Check out the xref:manual/api.adoc[Java API], {logging-services-url}/log4j/kotlin[Kotlin API], and {logging-services-url}/log4j/scala[Scala API] pages for further information.
diff --git a/src/site/antora/modules/ROOT/partials/manual/async-drawbacks.adoc b/src/site/antora/modules/ROOT/partials/manual/async-drawbacks.adoc
index e840334a73..9866ce36ac 100644
--- a/src/site/antora/modules/ROOT/partials/manual/async-drawbacks.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/async-drawbacks.adoc
@@ -24,8 +24,8 @@ In some rare cases, care must be taken with mutable messages.
Most of the time you don't need to worry about this.
Log4 will ensure that log messages like `logger.debug("My object is {}", myObject)` will use the state of the `myObject` parameter at the time of the call to `logger.debug()`.
The log message will not change even if `myObject` is modified later.
-It is safe to asynchronously log mutable objects because most xref:manual/messages.adoc[built-in `Message` implementations] take a snapshot of the parameters.
-There are some exceptions however: xref:manual/messages.adoc#MapMessage[`MapMessage`] and xref:manual/messages.adoc#StructuredDataMessage[`StructuredDataMessage`] are mutable by design, fields can be added to these messages after the message object was created.
+It is safe to asynchronously log mutable objects because most {log4j2-url}/manual/messages.adoc[built-in `Message` implementations] take a snapshot of the parameters.
+There are some exceptions however: {log4j2-url}/manual/messages.adoc#MapMessage[`MapMessage`] and {log4j2-url}/manual/messages.adoc#StructuredDataMessage[`StructuredDataMessage`] are mutable by design, fields can be added to these messages after the message object was created.
These messages should not be modified after they are logged with asynchronous loggers or asynchronous appenders; you may or may not see the modifications in the resulting log output.
Similarly, custom `Message` implementations should be designed with asynchronous use in mind, and either take a snapshot of their parameters at construction time, or document their thread-safety characteristics.
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-async.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-async.adoc
index 261e2ba843..0955f6a60d 100644
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-async.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-async.adoc
@@ -26,7 +26,7 @@
If `false`, Log4j will make sure the message is formatted in the caller thread, otherwise the formatting will occur on the asynchronous thread.
-**Remark**: messages annotated with link:../javadoc/log4j-api/org/apache/logging/log4j/message/AsynchronouslyFormattable[AsynchronouslyFormattable] will be formatted on the async thread regardless of this setting.
+**Remark**: messages annotated with {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/AsynchronouslyFormattable[AsynchronouslyFormattable] will be formatted on the async thread regardless of this setting.
[id=log4j.async.queueFullPolicy.type]
== `log4j.async.queueFullPolicy.type`
@@ -53,7 +53,7 @@ Discard:: when the queue is full, it drops the events whose level is equal or le
[cols="1h,5"]
|===
| Env. variable | LOG4J_ASYNC_QUEUE_FULL_POLICY_DISCARD_THRESHOLD
-| Type | link:../javadoc/log4j-api/org/apache/logging/log4j/Level[Level]
+| Type | {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/Level[Level]
| Default value | `INFO`
|===
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-configuration-factory.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-configuration-factory.adoc
index 80c0d9310e..a270bc25e4 100644
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-configuration-factory.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-configuration-factory.adoc
@@ -55,7 +55,7 @@ See also xref:manual/configuration.adoc#AutomaticConfiguration[Automatic Configu
[cols="1h,5"]
|===
| Env. variable | LOG4J_LEVEL
-| Type | link:../javadoc/log4j-api/org/apache/logging/log4j/Level[Level]
+| Type | {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/Level[Level]
| Default value | `ERROR`
|===
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-garbage-collection.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-garbage-collection.adoc
index 1aae6bffb9..f175a4a215 100644
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-garbage-collection.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-garbage-collection.adoc
@@ -66,7 +66,7 @@ This setting is only used if <<log4j.gc.enableDirectEncoders>> is set to `true`.
| Default value | `128`
|===
-In GC-free mode, this property determines the initial size of the reusable ``StringBuilder``s used by link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
+In GC-free mode, this property determines the initial size of the reusable ``StringBuilder``s used by {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
[id=log4j.gc.maxReusableMsgSize]
== `log4j.gc.maxReusableMsgSize`
@@ -78,7 +78,7 @@ In GC-free mode, this property determines the initial size of the reusable ``Str
| Default value | `518`
|===
-In GC-free mode, this property determines the maximum size of the reusable ``StringBuilder``s used by link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
+In GC-free mode, this property determines the maximum size of the reusable ``StringBuilder``s used by {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
The default value allows is equal to `2 × (2 × log4j.initialReusableMsgSize + 2) + 2` and allows the
``StringBuilder`` to be resized twice by the current JVM resize algorithm.
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-log-event.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-log-event.adoc
index 712eb9eeb7..313ad80610 100644
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-log-event.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-log-event.adoc
@@ -23,14 +23,14 @@
| LOG4J_LOG_EVENT_CONTEXT_DATA_TYPE
| Type
-| link:../javadoc/log4j-api/org/apache/logging/log4j/util/StringMap.html[Class<? extends StringMap>]
+| {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/util/StringMap.html[Class<? extends StringMap>]
| Default value
-| link:../javadoc/log4j-api/org/apache/logging/log4j/util/SortedArrayStringMap.html[SortedArrayStringMap]
+| {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/util/SortedArrayStringMap.html[SortedArrayStringMap]
|===
Fully qualified class name of a
-link:../javadoc/log4j-api/org/apache/logging/log4j/util/StringMap.html[StringMap]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/util/StringMap.html[StringMap]
implementation to use to store context data in log events.
The implementation must have:
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-logger-context.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-logger-context.adoc
index db8188d2d1..15045d638b 100644
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-logger-context.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-logger-context.adoc
@@ -30,7 +30,7 @@ A `ContextSelector` decides:
* how loggers are split among logger contexts,
* the
-link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[Logger]
+{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/Logger.html[Logger]
implementation to use.
The implementations available by default are:
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-message.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-message.adoc
index 19f1505d3b..bbd64054bb 100644
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-message.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-message.adoc
@@ -23,10 +23,10 @@
| LOG4J_MESSAGE_FACTORY
| Type
-| link:../javadoc/log4j-api/org/apache/logging/log4j/message/MessageFactory[Class<? extends MessageFactory>]
+| {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/MessageFactory[Class<? extends MessageFactory>]
| Default value
-| link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessageFactory[ReusableMessageFactory]
+| {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessageFactory[ReusableMessageFactory]
|===
-Fully qualified class name of a link:../javadoc/log4j-api/org/apache/logging/log4j/message/MessageFactory[MessageFactory] implementation that will be used by loggers if no explicit factory was specified.
\ No newline at end of file
+Fully qualified class name of a {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/MessageFactory[MessageFactory] implementation that will be used by loggers if no explicit factory was specified.
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-thread-context.adoc b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-thread-context.adoc
index 16ff1e07c6..34367d81ed 100644
--- a/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-thread-context.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/systemproperties/properties-thread-context.adoc
@@ -59,7 +59,7 @@ If `false`, the `ThreadContext` map is disabled.
| LOG4J_THREAD_CONTEXT_MAP_TYPE
| Type
-| link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[Class<? extends ThreadContextMap>] or predefined constant
+| {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[Class<? extends ThreadContextMap>] or predefined constant
| Default value
| `WebApp`
@@ -67,7 +67,7 @@ If `false`, the `ThreadContext` map is disabled.
(GC-free mode: `CopyOnWrite`)
|===
-Fully specified class name of a custom link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[ThreadContextMap] implementation class or one of the predefined constants:
+Fully specified class name of a custom {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[ThreadContextMap] implementation class or one of the predefined constants:
NoOp:: to disable the thread context,
WebApp:: a web application-safe implementation, that only binds JRE classes to `ThreadLocal` to prevent memory leaks,
diff --git a/src/site/antora/modules/ROOT/partials/properties-garbage-collection.adoc b/src/site/antora/modules/ROOT/partials/properties-garbage-collection.adoc
index 92a6ebc05d..71ea8953b9 100644
--- a/src/site/antora/modules/ROOT/partials/properties-garbage-collection.adoc
+++ b/src/site/antora/modules/ROOT/partials/properties-garbage-collection.adoc
@@ -68,7 +68,7 @@ This setting is only used if <<log4j2.enableDirectEncoders>> is set to `true`.
| Default value | `128`
|===
-In GC-free mode, this property determines the initial size of the reusable ``StringBuilder``s used by link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
+In GC-free mode, this property determines the initial size of the reusable ``StringBuilder``s used by {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
[id=log4j2.maxReusableMsgSize]
== `log4j2.maxReusableMsgSize`
@@ -80,7 +80,7 @@ In GC-free mode, this property determines the initial size of the reusable ``Str
| Default value | `518`
|===
-In GC-free mode, this property determines the maximum size of the reusable ``StringBuilder``s used by link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
+In GC-free mode, this property determines the maximum size of the reusable ``StringBuilder``s used by {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/message/ReusableMessage[ReusableMessages] for formatting purposes.
The default value allows is equal to `2 × (2 × log4j.initialReusableMsgSize + 2) + 2` and allows the
`StringBuilder` to be resized twice by the current JVM resize algorithm.
@@ -111,7 +111,7 @@ This property determines the maximum size of the reusable ``StringBuilder``s use
| Default value | `32`
|===
-The link:../javadoc/log4j-api/org/apache/logging/log4j/util/Unbox[Unbox] utility class can be used by users to format primitive values without incurring in the boxing allocation cost.
+The {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/util/Unbox[Unbox] utility class can be used by users to format primitive values without incurring in the boxing allocation cost.
This property specifies the maximum number of primitive arguments to a log message that will be cached and usually does not need to be changed.
diff --git a/src/site/antora/modules/ROOT/partials/properties-thread-context.adoc b/src/site/antora/modules/ROOT/partials/properties-thread-context.adoc
index a3936eb2e4..e6cd66610e 100644
--- a/src/site/antora/modules/ROOT/partials/properties-thread-context.adoc
+++ b/src/site/antora/modules/ROOT/partials/properties-thread-context.adoc
@@ -58,13 +58,13 @@ If `true`, the `ThreadContext` map is disabled.
[cols="1h,5"]
|===
| Env. variable | LOG4J_THREAD_CONTEXT_MAP
-| Type | link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[Class<? extends ThreadContextMap>] or predefined constant
+| Type | {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[Class<? extends ThreadContextMap>] or predefined constant
| Default value | `WebApp`
(GC-free mode: `CopyOnWrite`)
|===
-Fully specified class name of a custom link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[ThreadContextMap] implementation class or one of the predefined constants:
+Fully specified class name of a custom {log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap[ThreadContextMap] implementation class or one of the predefined constants:
NoOp:: to disable the thread context,
WebApp:: a web application-safe implementation, that only binds JRE classes to `ThreadLocal` to prevent memory leaks,