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
The following commit(s) were added to refs/heads/main by this push:
new f683f6adfb Revamp the F.A.Q. page (#2506, #2549)
f683f6adfb is described below
commit f683f6adfbfccda6c295902ae89133a610ecee85
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Tue Apr 30 13:27:09 2024 +0200
Revamp the F.A.Q. page (#2506, #2549)
Co-authored-by: Piotr P. Karwasz <[email protected]>
---
.../antora/modules/ROOT/images/whichjar-2.x.png | Bin 68381 -> 0 bytes
.../modules/ROOT/images/whichjar-log4j-1.2-api.png | Bin 24992 -> 0 bytes
.../modules/ROOT/images/whichjar-log4j-api.png | Bin 16515 -> 0 bytes
.../modules/ROOT/images/whichjar-slf4j-2.x.png | Bin 26650 -> 0 bytes
src/site/antora/modules/ROOT/pages/faq.adoc | 401 +++++----------------
5 files changed, 94 insertions(+), 307 deletions(-)
diff --git a/src/site/antora/modules/ROOT/images/whichjar-2.x.png
b/src/site/antora/modules/ROOT/images/whichjar-2.x.png
deleted file mode 100644
index e72a78fe08..0000000000
Binary files a/src/site/antora/modules/ROOT/images/whichjar-2.x.png and
/dev/null differ
diff --git a/src/site/antora/modules/ROOT/images/whichjar-log4j-1.2-api.png
b/src/site/antora/modules/ROOT/images/whichjar-log4j-1.2-api.png
deleted file mode 100644
index 8b54810904..0000000000
Binary files a/src/site/antora/modules/ROOT/images/whichjar-log4j-1.2-api.png
and /dev/null differ
diff --git a/src/site/antora/modules/ROOT/images/whichjar-log4j-api.png
b/src/site/antora/modules/ROOT/images/whichjar-log4j-api.png
deleted file mode 100644
index 194196aad3..0000000000
Binary files a/src/site/antora/modules/ROOT/images/whichjar-log4j-api.png and
/dev/null differ
diff --git a/src/site/antora/modules/ROOT/images/whichjar-slf4j-2.x.png
b/src/site/antora/modules/ROOT/images/whichjar-slf4j-2.x.png
deleted file mode 100644
index b42fb274b3..0000000000
Binary files a/src/site/antora/modules/ROOT/images/whichjar-slf4j-2.x.png and
/dev/null differ
diff --git a/src/site/antora/modules/ROOT/pages/faq.adoc
b/src/site/antora/modules/ROOT/pages/faq.adoc
index 0dd19e9281..a1b3fef318 100644
--- a/src/site/antora/modules/ROOT/pages/faq.adoc
+++ b/src/site/antora/modules/ROOT/pages/faq.adoc
@@ -17,404 +17,191 @@ Licensed to the Apache Software Foundation (ASF) under
one or more
= F.A.Q.
-[#missing_core]
-== I'm seeing this error "Unable to locate a logging implementation, using
SimpleLogger". What is wrong?
-
-You have the log4j-api-2.x jar file in your classpath but you still need to
add the log4j-core-2.x jar to the classpath.
-(Also, it looks like you are using an old version of Log4j 2.
-You may want to upgrade.)
-
-[#which_jars]
-== Which JAR files do I need?
-
-You need at least the log4j-api-2.x and the log4j-core-2.x jar files.
-
-The other jars are necessary if your application calls the API of another
logging framework and you want to route logging calls to the Log4j 2
implementation.
-
-image:whichjar-2.x.png[Diagram showing which JARs correspond to which systems]
-
-[#which_jars_log4j-to-slf4j] You can use the log4j-to-slf4j adapter jar when
your application calls the Log4j 2 API and you want to route logging calls to a
SLF4J implementation.
-
-image:whichjar-slf4j-2.x.png[Diagram showing the dependency flow to use Log4j
2 API with SLF4J]
-
-Some of the Log4j components have features with optional dependencies.
-See xref:runtime-dependencies.adoc[the runtime dependencies page] for more
information.
-
-[#exclusions]
-== How do I exclude conflicting dependencies?
-
-There are several scenarios where you may end up with conflicting
dependencies, especially transitively included ones.
-The following table shows for each Log4j dependency on the left (implicit
groupId of `org.apache.logging.log4j`), the following dependencies on the right
can be safely excluded (given in the format `groupId:artifactId`).
-
-[%header,cols="1m,3m"]
-|===
-|Log4j dependency
-|Dependencies to exclude
-
-|log4j-1.2-api
-|log4j:log4j +
-org.slf4j:log4j-over-slf4j
-
-|log4j-core
-|log4j:log4j +
-ch.qos.logback:logback-core +
-org.apache.logging.log4j:log4j-to-slf4j
-
-|log4j-jcl
-|org.slf4j:jcl-over-slf4j
-
-|log4j-jul
-|org.slf4j:jul-to-slf4j
-
-|log4j-slf4j-impl
-|org.apache.logging.log4j:log4j-to-slf4j +
-ch.qos.logback:logback-core
-|===
-
-Using Apache Maven, dependencies can be globally excluded in your project like
so:
-
-[source,xml]
-----
-<dependencies>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>1.2.17</version>
- <scope>provided</scope>
- </dependency>
-</dependencies>
-----
-
-Dependencies can be explicitly excluded for specific dependencies as well.
-For example, to use a project with Log4j 2 instead of Log4j 1.x:
-
-[source,xml]
-----
-<dependencies>
- <dependency>
- <groupId>com.example</groupId>
- <artifactId>example-project</artifactId>
- <version>1.0</version>
- <exclusions>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>${Log4jReleaseVersion}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-slf4j-impl</artifactId>
- <version>${Log4jReleaseVersion}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-1.2-api</artifactId>
- <version>${Log4jReleaseVersion}</version>
- </dependency>
-</dependencies>
-----
-
-Dependencies can be globally excluded in Gradle like so:
-
-[source]
-----
-configurations {
- all*.exclude group: 'log4j', module: 'log4j'
-}
-----
-
-The equivalent Gradle config for the above Maven exclusion would look like:
-
-[source]
-----
-dependencies {
- compile('com.example:example-project:1.0') {
- exclude group: 'log4j', module: 'log4j'
- exclude group: 'org.slf4j', module: 'slf4j-log4j12'
- }
- compile('org.apache.logging.log4j:log4j-core:${Log4jReleaseVersion}')
- compile('org.apache.logging.log4j:log4j-slf4j-impl:${Log4jReleaseVersion}')
- compile('org.apache.logging.log4j:log4j-1.2-api:${Log4jReleaseVersion}')
-}
-----
+This page compiles a list of frequently asked questions.
+If you don't find the answer to your question, please consult to
link:{logging-services-url}/support.html[the support page].
[#config_location]
== How do I specify the configuration file location?
-By default, Log4j looks for a configuration file named *log4j2.xml* (not
log4j.xml) in the classpath.
+By default, Log4j looks for a configuration file named `log4j2.xml`,
`log4j2.properties`, etc. in the classpath.
+
+[WARNING]
+====
+Log4j 1 (which has reached its end-of-life in 2015!) uses `log4j.xml`.
+Log4j 2 and onwards use `log4j2.xml`.
+====
-You can also specify the full path of the configuration file with this system
property: `-Dlog4j.configurationFile=path/to/log4j2.xml`
+You can also specify the full path of the configuration file using a system
property: +
+`-Dlog4j2.configurationFile=/path/to/log4j2.xml`
That property can also be included in a classpath resource file named
`log4j2.component.properties`.
Web applications can specify the Log4j configuration file location with a
servlet context parameter.
-See http://logging.apache.org/log4j/2.x/manual/webapp.html#ContextParams[this
section] of the Using Log4j 2 in Web Applications manual page.
+See xref:manual/webapp.adoc#ContextParams[the related page on web
applications].
+
+Refer to xref:manual/configuration.adoc[the Configuration page] for further
details.
[#config_from_code]
-== How do I configure log4j2 in code without a configuration file?
+== How do I configure Log4j programmatically?
-Starting with version 2.4, Log4j 2 provides an
xref:manual/customconfig.adoc[API for programmatic configuration] The new
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.html[`ConfigurationBuilder`
API] allows you to create Configurations in code by constructing component
definitions without requiring you to know about the internals of actual
configuration objects like Loggers and Appenders.
+Starting with version `2.4`, Log4j provides xref:manual/customconfig.adoc[an
API for programmatic configuration].
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.html[The
new `ConfigurationBuilder` API] allows you to create ``Configuration``s in
code by constructing component definitions without requiring you to know about
the internals of actual configuration objects like loggers and appenders.
[#reconfig_from_code]
-== How do I reconfigure log4j2 in code with a specific configuration file?
+== How do I reconfigure Log4j programmatically?
-See the below example.
-Be aware that this LoggerContext class is not part of the public API so your
code may break with any minor release.
+You can reconfigure Log4j programmatically using
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configurator.html[the
`Configurator` API] as follows:
[source,java]
----
-// import org.apache.logging.log4j.core.LoggerContext;
-
-LoggerContext context = (org.apache.logging.log4j.core.LoggerContext)
LogManager.getContext(false);
-File file = new File("path/to/a/different/log4j2.xml");
+import org.apache.logging.log4j.core.config.Configurator;
-// this will force a reconfiguration
-context.setConfigLocation(file.toURI());
+URI configSourceUri = new File("/path/to/a/different/log4j2.xml").toURI();
+Configurator.reconfigure(configSourceUri);
----
[#shutdown]
-== How do I shut down log4j2 in code?
+== How do I shut down Log4j programmatically?
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 system property
`log4j.shutdownHookEnabled` is set to `false`).
-Web applications should include the log4j-web module in their classpath which
disables the shutdown hook but instead cleans up log4j resources when the web
application is stopped.
+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, xref:manual/webapp.adoc[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 do so as in the
below example.
-Note that there is an optional parameter for specifying which `LoggerContext`
to shut down.
+[#reconfig_level_from_code]
+== How do I set a logger level programmatically?
+
+You can set the level of a logger using
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configurator.html[`Configurator`]
from Log4j Core:
[source,java]
----
-import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.config.Configurator;
-// ...
+// Set the level of particular logger associated with a class
+Configurator.setLevel("com.example.Foo", Level.DEBUG);
-LogManager.shutdown();
+// Set the level of the root logger
+Configurator.setRootLevel(Level.DEBUG);
----
[#config_sep_appender_level]
== How do I send log messages with different levels to different appenders?
+
You don't need to declare separate loggers to achieve this.
You can set the logging level on the `AppenderRef` element.
[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="WARN">
- <Appenders>
+<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="https://logging.apache.org/xml/ns"
+ xsi:schemaLocation="
+ https://logging.apache.org/xml/ns
+ https://logging.apache.org/xml/ns/log4j-config-3.xsd">
+ <appenders>
<File name="file" fileName="app.log">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern>
- </PatternLayout>
+ <PatternLayout pattern="%d %p %c{1.} [%t] %m %ex%n"/>
</File>
- <Console name="STDOUT" target="SYSTEM_OUT">
+ <Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
- </Appenders>
- <Loggers>
- <Root level="trace">
+ </appenders>
+ <loggers>
+ <root level="WARN">
<AppenderRef ref="file" level="DEBUG"/>
- <AppenderRef ref="STDOUT" level="INFO"/>
- </Root>
- </Loggers>
+ <AppenderRef ref="stdout" level="INFO"/>
+ </root>
+ </loggers>
</Configuration>
----
[#troubleshooting]
== How do I debug my configuration?
-First, make sure you have <<which_jars,the right jar files>> on your classpath.
-You need at least log4j-api and log4j-core.
-
-Next, check the name of your configuration file.
-By default, log4j2 will look for a configuration file named `log4j2.xml` on
the classpath.
-Note the "2" in the file name!
-(See the xref:manual/configuration.adoc#AutomaticConfiguration[configuration
manual page] for more details.)
-
-*From log4j-2.9 onward*
+. Make sure you have xref:manual/installation.adoc[the right JAR files] on
your classpath.
-From log4j-2.9 onward, log4j2 will print all internal logging to the console
if system property `log4j2.debug` is either defined empty or its value equals
to `true` (ignoring case).
+. Check the name of your configuration file.
+By default, Log4j looks for a configuration file named `log4j2.xml` on the
classpath.
+Note the `2` in the file name!
+(See xref:manual/configuration.adoc[the Configuration page] for more details.)
-*Prior to log4j-2.9*
+. Increase the logging verbosity of the internal status logger: +
+`-Dlog4j2.statusLoggerLevel=TRACE`
-Prior to log4j-2.9, there are two places where internal logging can be
controlled:
-
-If the configuration file is found correctly, log4j2 internal status logging
can be controlled by setting `<Configuration status="trace">` in the
configuration file.
-This will display detailed log4j2-internal log statements on the console about
what happens during the configuration process.
-This may be useful to trouble-shoot configuration issues.
-By default the status logger level is WARN, so you only see notifications when
there is a problem.
-
-If the configuration file is not found correctly, you can still enable log4j2
internal status logging by setting system property
`-Dorg.apache.logging.log4j.simplelog.StatusLogger.level=TRACE`.
+. Enable all internal debug logging: `-Dlog4j2.debug`.
+This disables level-based status logger filtering and effectively allows all
status logs.
[#separate_log_files]
== How do I dynamically write to separate log files?
-Look at the
http://logging.apache.org/log4j/2.x/manual/appenders.html#RoutingAppender[RoutingAppender].
-You can define multiple routes in the configuration, and put values in the
`ThreadContext` map that determine which log file subsequent events in this
thread get logged to.
-
-You can use the `ThreadContext` map value to determine the log file name.
-
-[source,xml]
-----
-<Routing name="Routing">
- <Routes pattern="$${ctx:ROUTINGKEY}">
-
- <!-- This route is chosen if ThreadContext has value 'special' for key
ROUTINGKEY. -->
- <Route key="special">
- <RollingFile name="Rolling-${ctx:ROUTINGKEY}"
fileName="logs/special-${ctx:ROUTINGKEY}.log"
-
filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}-special-%d{yyyy-MM-dd}-%i.log.gz">
- <PatternLayout>
- <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy interval="6" modulate="true" />
- <SizeBasedTriggeringPolicy size="10 MB" />
- </Policies>
- </RollingFile>
- </Route>
-
- <!-- This route is chosen if ThreadContext has no value for key
ROUTINGKEY. -->
- <Route key="$${ctx:ROUTINGKEY}">
- <RollingFile name="Rolling-default" fileName="logs/default.log"
- filePattern="./logs/${date:yyyy-MM}/default-%d{yyyy-MM-dd}-%i.log.gz">
- <PatternLayout>
- <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy interval="6" modulate="true" />
- <SizeBasedTriggeringPolicy size="10 MB" />
- </Policies>
- </RollingFile>
- </Route>
-
- <!-- This route is chosen if ThreadContext has a value for ROUTINGKEY
- (other than the value 'special' which had its own route above).
- The value dynamically determines the name of the log file. -->
- <Route>
- <RollingFile name="Rolling-${ctx:ROUTINGKEY}"
fileName="logs/other-${ctx:ROUTINGKEY}.log"
-
filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}-other-%d{yyyy-MM-dd}-%i.log.gz">
- <PatternLayout>
- <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy interval="6" modulate="true" />
- <SizeBasedTriggeringPolicy size="10 MB" />
- </Policies>
- </RollingFile>
- </Route>
- </Routes>
-</Routing>
-----
-
-[#reconfig_level_from_code]
-== How do I set a logger's level programmatically?
-
-You can set a logger's level with the class
link:javadoc/log4j-core/org/apache/logging/log4j/core/config/Configurator.html[`Configurator`]
from Log4j Core.
-Be aware that the `Configurator` class is not part of the public API.
-
-[source,java]
-----
-// org.apache.logging.log4j.core.config.Configurator;
-
-Configurator.setLevel("com.example.Foo", Level.DEBUG);
-
-// You can also set the root logger:
-Configurator.setRootLevel(Level.DEBUG);
-----
-
-[#retention]
-== How do I set my log archive retention policy?
-How do I delete old log archives?
-
-The `DefaultRolloverStrategy` of the Rolling File appender (and Rolling Random
Access File appender) supports a
xref:manual/appenders.adoc#CustomDeleteOnRollover[Delete] element.
-
-Starting at a specified base directory, you can delete all files for which
some condition holds true, for example all files that match a given file name
pattern and are older than some number of days.
-More complex conditions are possible, and if the built-in conditions are not
sufficient, users can provide custom conditions by creating
xref:manual/appenders.adoc#DeletePathCondition[plugin conditions] or by writing
a xref:manual/appenders.adoc#ScriptCondition[script condition].
+You can use xref:manual/appenders.adoc#RoutingAppender[the routing appender]
to evaluate a log message and forward it to a particular appender.
[#api-tradeoffs]
-== What are the trade-offs of using the Log4j 2 API versus the SLF4J API?
+== What are the trade-offs of using Log4j API versus SLF4J?
-The Log4j 2 API and SLF4J have a lot in common.
+Log4j API and SLF4J have a lot in common.
They both share the objective of cleanly separating the logging API from the
implementation.
-We believe that the Log4j 2 API can help make your application more performant
while offering more functionality and more flexibility.
+We believe that Log4j API can help make your application more performant while
offering more functionality and more flexibility.
-There may be a concern that using the Log4j 2 API will tightly couple your
application to Log4j 2.
-This is not the case: applications coded to the Log4j 2 API always have the
option to use any SLF4J-compliant library as their logging implementation with
the log4j-to-slf4j adapter.
-See the <<which_jars_log4j-to-slf4j,which jars>> FAQ entry for details.
+There may be a concern that using the Log4j API will tightly couple your
application to Log4j.
+This is not the case: applications coded to Log4j API always have the option
to use any SLF4J-compliant logging implementation with the `log4j-to-slf4j`
bridge.
+See xref:manual/installation.adoc[the Installation page] for details.
-There are several advantages to using the Log4j 2 API:
+There are several advantages to using Log4j API:
-* SLF4J forces your application to log Strings.
-The Log4j 2 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
Strings.
-* The Log4j 2 API offers support for logging xref:manual/messages.adoc[Message
objects].
+* 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].
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.
-* The Log4j 2 API has support for Java 8
xref:manual/api.adoc#LambdaSupport[lambda expressions].
-* The Log4j 2 API has better support for
xref:manual/garbagefree.adoc[garbage-free logging]: it avoids creating vararg
arrays and avoids creating Strings when logging CharSequence objects.
+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 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]
-== Is Log4j 2 still garbage-free when I use the SLF4J API?
+== Is Log4j still garbage-free when I use SLF4J?
-Yes, the log4j-slf4j-impl binding (together with log4j-core) implements the
`org.slf4j.Logger` methods to be GC-free.
+If you use SLF4J as your logging API and Log4j Core as the logging
implementation, yes.
+The `log4j-slf4j-impl` and `log4j-slf4j2-impl` bridges (together with
`log4j-core`) implement the `org.slf4j.Logger` methods to be garbage-free.
However, bear in mind that there are some limitations:
-The SLF4J API only offers up to two parameters for a parameterized message.
-More than that uses varargs which creates a temporary object for the parameter
array.
-The Log4j 2.6 API has methods for up to ten unrolled parameters.
+* The SLF4J API only offers up to two parameters for a parameterized message.
+More than that uses ``vararg``s, which create a temporary object for the
parameter array.
+In contrast, Log4j API has methods for up to ten unrolled parameters.
-Another consideration is that the SLF4J API forces your application to log
Strings.
-Log4j 2 API lets you log any java.lang.CharSequence, and even any Objects.
-Log4j can log any Object that implements `java.lang.CharSequence` or
`org.apache.logging.log4j.util.StringBuilderFormattable` without creating
garbage.
+* SLF4J forces your application to log ``String``s.
+Log4j API lets you log any `CharSequence` or `Object`.
+Log4j Core can log any `Object` that implements `CharSequence` or
`org.apache.logging.log4j.util.StringBuilderFormattable` without creating
garbage.
-The
https://www.slf4j.org/api/org/slf4j/spi/LocationAwareLogger.html#log-org.slf4j.Marker-java.lang.String-int-java.lang.String-java.lang.Object:A-java.lang.Throwable-[`org.slf4j.spi.LocationAwareLogger::log`]
method is not yet implemented in a garbage-free manner in the log4j-slf4j-impl
binding.
+* The
https://www.slf4j.org/api/org/slf4j/spi/LocationAwareLogger.html#log(org.slf4j.Marker,java.lang.String,int,java.lang.String,java.lang.Object%5B%5D,java.lang.Throwable)[`org.slf4j.spi.LocationAwareLogger::log`]
method is not yet implemented in a garbage-free manner in the
`log4j-slf4j-impl` and `log4j-slf4j2-impl` bridges.
It creates a new message object for each call.
[#gc-free-domain-object]
== How do I log my domain object without creating garbage?
-One option is to let the domain object implement java.lang.CharSequence.
+One option is to let the domain object implement `CharSequence`.
However, for many domain objects it may not be trivial to implement this
without allocating temporary objects.
An alternative is to implement the
`org.apache.logging.log4j.util.StringBuilderFormattable` interface.
-If an object is logged that implements this interface, its `formatTo` method
is called instead of `toString()`.
-
-[source,java]
-----
-package org.apache.logging.log4j.util;
-public interface StringBuilderFormattable {
- /**
- * Writes a text representation of this object into the specified {@code
StringBuilder},
- * ideally without allocating temporary objects.
- *
- * @param buffer the StringBuilder to write into
- */
- void formatTo(StringBuilder buffer);
-}
-----
+If an object is logged that implements this interface, its
`formatTo(StringBuilder)` method is called instead of `toString()`.
[#logger-wrapper]
-== How do I create a custom logger wrapper that shows the correct class,
method and line number?
+== How do I create a custom logger wrapper that shows the correct class,
method, and line number?
Log4j remembers the fully qualified class name (FQCN) of the logger and uses
this to walk the stack trace for every log event when configured to print
location.
-(Be aware that logging with location is slow and may impact the performance of
your application.)
+
+[WARNING]
+====
+Be aware that logging with location is slow and may impact the performance of
your application.
+====
The problem with custom logger wrappers is that they have a different FQCN
than the actual logger, so Log4j can't find the place where your custom logger
was called.
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
https://logging.apache.org/log4j/2.x/manual/customloglevels.html#CustomLoggers[here].
-
+This tool was originally meant to support custom log levels and is documented
xref:manual/customloglevels.adoc#CustomLoggers[here].
The generated logger code will take care of the FQCN.
[#proguard-rules]