| //// |
| 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...] |