blob: 525c5d54e0e1fb7bb73d8dd2b091b8975c800536 [file] [log] [blame]
////
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.
////
= Log4j API
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]
====
include::partial$concepts.adoc[tags=inc;api;impl]
====
[TIP]
====
Are you looking for a crash course on how to use Log4j in your application or library?
See xref:manual/getting-started.adoc[].
You can also check out xref:manual/installation.adoc[] for the complete installation instructions.
====
Log4j API provides
* A logging API that libraries and applications can code to
* <<simple-logger,A minimal logging implementation (aka. Simple logger)>>
* Adapter components to create a logging implementation
This page tries to cover the most prominent Log4j API features.
[TIP]
====
Did you know that Log4j provides specialized APIs for Kotlin and Scala?
Check out
{logging-services-url}/log4j/kotlin/index.html[Log4j Kotlin]
and
{logging-services-url}/log4j/scala/index.html[Log4j Scala]
projects for details.
====
[#intro]
== Introduction
include::partial$manual/api-intro.adoc[leveloffset=+1]
include::partial$manual/log-event.adoc[]
[#best-practice]
== Best practices
There are several widespread bad practices while using Log4j API.
Let's try to walk through the most common ones and see how to fix them.
[#best-practice-toString]
=== Don't use `toString()`
include::partial$manual/api-best-practice-dont-use-toString.adoc[]
[#best-practice-exception]
=== Pass exception as the last extra argument
include::partial$manual/api-best-practice-exception-as-last-argument.adoc[]
[#best-practice-concat]
=== Don't use string concatenation
include::partial$manual/api-best-practice-dont-use-string-concat.adoc[]
[#best-practice-supplier]
=== Use ``Supplier``s to pass computationally expensive arguments
include::partial$manual/api-best-practice-use-supplier.adoc[]
[#loggers]
== Loggers
link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[`Logger`]s are the primary entry point for logging.
In this section we will introduce you to further details about ``Logger``s.
[TIP]
====
Refer to xref:manual/architecture.adoc[] to see where ``Logger``s stand in the big picture.
====
[#logger-names]
=== 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 `.` (dot) 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 provides that as the default when the logger name parameter is either omitted or is null.
For example, all `Logger`-typed variables below will have a name of `com.example.LoggerNameTest`:
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tags=class;!examples]
----
[TIP]
====
**We suggest you to use `LogManager.getLogger()` without any arguments** since it delivers the same functionality with less characters and is not prone to copy-paste errors.
====
[#logger-message-factories]
=== Logger message factories
Loggers translate
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=example1,indent=0]
----
calls to the appropriate canonical logging method:
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=example2,indent=0]
----
Note that how `Hello, {}!` should be encoded given the `\{name}` array as argument completely depends on the link:../javadoc/log4j-api/org/apache/logging/log4j/message/MessageFactory.html[`MessageFactory`] employed.
Log4j allows users to customize this behaviour in several `getLogger()` methods of link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html[`LogManager`]:
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=example3,indent=0]
----
<1> Create a logger using the default message factory
<2> Use default parameter placeholders, that is, `{}` style
<3> Explicitly provide the message factory, that is, link:../javadoc/log4j-api/org/apache/logging/log4j/message/StringFormatterMessageFactory.html[`StringFormatterMessageFactory`].
Note that there are several other `getLogger()` methods accepting a `MessageFactory`.
<4> Note the placeholder change from `{}` to `%s`!
Passed `Hello, %s!` and `name` arguments will be implicitly translated to a `String.format("Hello, %s!", name)` call due to the employed `StringFormatterMessageFactory`.
Log4j bundles several xref:manual/messages.adoc[predefined message factories].
Some common ones are accessible through convenient factory methods, which we will cover below.
[#formatter-logger]
=== Formatter logger
The `Logger` instance returned by default replaces the occurrences of `{}` placeholders with the `toString()` output of the associated parameter.
If you need more control over how the parameters are formatted, you can also use the https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/Formatter.html#syntax[`java.util.Formatter`] format strings by obtaining your `Logger` using link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html#getFormatterLogger(java.lang.Class)[`LogManager#getFormatterLogger()`]:
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=formatter,indent=0]
----
Loggers returned by `getFormatterLogger()` are referred as *formatter loggers*.
[#printf]
==== `printf()` method
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 `Logger#printf()` method:
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=printf,indent=0]
----
[#formatter-perf]
==== Formatter performance
Keep in mind that, contrary to the formatter logger, the default Log4j logger (i.e., `{}`-style parameters) is heavily optimized for several use cases and can operate xref:manual/garbagefree.adoc[garbage-free] when configured correctly.
You might reconsider your formatter logger usages for latency sensitive applications.
[#event-logger]
=== Event logger
link:../javadoc/log4j-api/org/apache/logging/log4j/EventLogger.html[`EventLogger`] is a convenience to log xref:manual/messages.adoc#StructuredDataMessage[`StructuredDataMessage`]s, which format their content in a way compliant with https://datatracker.ietf.org/doc/html/rfc5424#section-6[the Syslog message format described in RFC 5424].
[WARNING]
====
*Event Logger is deprecated for removal!*
We advise users to switch to plain `Logger` instead.
====
xref:manual/eventlogging.adoc[Read more on event loggers...]
[#simple-logger]
=== Simple logger
Even though Log4j Core is the reference implementation of Log4j API, Log4j API itself also provides a very minimalist implementation: _Simple Logger_.
This is a convenience for environments where either a fully-fledged logging implementation is missing, or cannot be included for other reasons.
`SimpleLogger` is the fallback Log4j API implementation if no other is available in the classpath.
xref:manual/simple-logger.adoc[Read more on the simple logger...]
[#status-logger]
=== Status logger
_Status Logger_ is a standalone, self-sufficient `Logger` implementation to record events that occur in the logging system (i.e., Log4j) itself.
It is the logging system used by Log4j for reporting status of its internals.
Users can use the status logger to either emit logs in their custom Log4j components, or troubleshoot a Log4j configuration.
xref:manual/status-logger.adoc[Read more on the status logger...]
[#fluent-api]
== Fluent API
The fluent API allows you to log using a fluent interface:
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=fluent,indent=0]
----
xref:manual/logbuilder.adoc[Read more on the Fluent API...]
[#fish-tagging]
== Fish tagging
Just as a fish can be tagged and have its movement tracked (aka. _fish tagging_ footnote:[Fish tagging is first described by Neil Harrison in the _"Patterns for Logging Diagnostic Messages"_ chapter of https://dl.acm.org/doi/10.5555/273448[_"Pattern Languages of Program Design 3"_ edited by R. Martin, D. Riehle, and F. Buschmann in 1997].]), 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.
You can use them for several purposes, such as:
* Provide extra information while serializing the log event
* Allow filtering of information so that it does not overwhelm the system or the individuals who need to make use of it
Log4j provides fish tagging in several flavors:
[#levels]
=== Levels
Log levels are used to categorize log events by severity.
Log4j contains predefined levels, of which the most common are `DEBUG`, `INFO`, `WARN`, and `ERROR`.
Log4j also allows you to introduce your own custom levels too.
xref:manual/customloglevels.adoc[Read more on custom levels...]
[#markers]
=== Markers
Markers are programmatic labels developers can associate to log statements:
[source,java]
----
include::example$manual/api/MyApp.java[tag=class,indent=0]
----
xref:manual/markers.adoc[Read more on markers...]
[#thread-context]
=== Thread Context
Just like https://docs.oracle.com/javase/{java-target-version}/docs/api/java/lang/ThreadLocal.html[Java's `ThreadLocal`], _Thread Context_ facilitates associating information with the executing thread and making this information accessible to the rest of the logging system.
Thread Context offers both
* map-structured referred to as _Thread Context Map_ or _Mapped Diagnostic Context (MDC)_
* stack-structured referred to as _Thread Context Stack_ or _Nested Diagnostic Context (NDC)_
storage:
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=thread-context1,indent=0]
include::example$manual/api/LoggerNameTest.java[tag=thread-context2,indent=0]
include::example$manual/api/LoggerNameTest.java[tag=thread-context3,indent=0]
----
<1> Adding properties to the thread context map
<2> Pushing properties to the thread context stack
<3> Added properties can later on be used to, for instance, filter the log event, provide extra information in the layout, etc.
<4> Popping the last pushed property from the thread context stack
<5> Clearing the thread context (for both stack and map!)
xref:manual/thread-context.adoc[Read more on Thread Context]...
[#messages]
== Messages
Whereas almost every other logging API and implementation accepts only `String`-typed input as message, Log4j generalizes this concept with a `Message` contract.
Customizability of the message type enables users to **have complete control over how a message is encoded** by Log4j.
This liberal approach allows applications to choose the message type best fitting to their logging needs; they can log plain ``String``s, or custom `PurchaseOrder` objects.
Log4j provides several predefined message types to cater for common use cases:
* Simple `String`-typed messages:
+
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=string,indent=0]
----
* `String`-typed parameterized messages:
+
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=parameterized,indent=0]
----
* `Map`-typed messages:
+
[source,java]
----
include::example$manual/api/LoggerNameTest.java[tag=map,indent=0]
----
xref:manual/messages.adoc[Read more on messages...]
[#flow-tracing]
== Flow tracing
The `Logger` class provides `traceEntry()`, `traceExit()`, `catching()`, `throwing()` methods that are quite useful for following the execution path of applications.
These methods generate log events that can be filtered separately from other debug logging.
xref:manual/flowtracing.adoc[Read more on flow tracing...]