blob: 187b6d37e0c8e6adc571cd7b8f47c8277ab54536 [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.
////
= Messages
Unlike other logging APIs, which either restrict the description of log events to (possibly interpolated) Java ``String``s or allow generic Java ``Object``s, the Log4j API encapsulates every log message into the logging-specific link:../javadoc/log4j-api/org/apache/logging/log4j/message/Message.html[`Message`] interface, before passing it to the logging implementation.
Such an approach opens to developers a wide range of customization possibilities.
include::partial$manual/log-event.adoc[]
[#usage]
== Usage
While internally Log4j uses `Message` objects, the `Logger` interface provides various shortcut methods to create the most commonly used messages:
* To create a <<SimpleMessage,`SimpleMessage`>> from a `String` argument, the following logger calls are equivalent:
+
[source,java,indent=0]
----
include::example$manual/messages/MessagesExample.java[tag=simple]
----
* To create a <<ParameterizedMessage,`ParameterizedMessage`>> from a format `String` and an array of object parameters, the following logger calls are equivalent:
+
[source,java,indent=0]
----
include::example$manual/messages/MessagesExample.java[tag=parameterized]
----
*In most cases, this is sufficient.*
Nex to use cases sufficed with `String`-based messages, the link:../javadoc/log4j-api/org/apache/logging/log4j/message/Message.html[`Message`] interface abstraction also allows users to log custom objects.
This effectively provides logging convenience in certain use cases.
For instance, imagine a scenario that uses a domain event to signal authentication failures:
[source,java]
----
record LoginFailureEvent(String userName, InetSocketAddress remoteAddress) {}
----
When the developer wants to log a message reporting the event, we can see that the string construction becomes more challenging to read:
[source,java,indent=0]
----
include::example$manual/messages/MessagesExample.java[tag=complex]
----
By extending the `Message` interface, developers can simplify the reporting of a login failure:
[source,java,indent=0]
----
include::example$manual/messages/MessagesExample.java[tag=loginFailure]
----
<1> Domain model needs to implement the `Message` interface
<2> `getFormattedMessage()` provides the `String` to be logged
As a result, logging of `LoginFailureEvent` instances can be simplified as follows:
[source,java,indent=0]
----
include::example$manual/messages/MessagesExample.java[tag=complex-message]
----
[#collection]
== Collection
This section explains predefined Log4j `Message` implementations addressing certain use cases.
We will group this collection into following titles:
* <<collection-string,Types intended for plain `String`-based messages>>
* <<collection-structured,Types intended for structured logging>>
[#collection-string]
=== String-based types
This section explains message types intended for human-readable `String`-typed output.
[#FormattedMessage]
==== `FormattedMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/FormattedMessage.html[`FormattedMessage`] is intended as a generic entry point to actual message implementations that use pattern-based formatting.
It works as follows:
. If the input is a valid https://docs.oracle.com/javase/{java-target-version}/docs/api/java/text/MessageFormat.html[`MessageFormat`] pattern, use <<MessageFormatMessage>>
. If the input is a valid https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/Formatter.html#syntax[`String.format()` pattern], use <<StringFormattedMessage>>
. Otherwise, use <<ParameterizedMessage>>
[WARNING]
====
Due to checks involved, `FormattedMessage` has an extra performance overhead compared to directly using a concrete `Message` implementation.
====
[#LocalizedMessage]
==== `LocalizedMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/LocalizedMessage.html[`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>>.
[WARNING]
====
`LocalizedMessage` is primarily provided for compatibility with {logging-services-url}/log4j/1.x[Log4j 1].
We advise you to perform log message localization at the representation layer of your application, e.g., the client UI.
====
[#MessageFormatMessage]
==== `MessageFormatMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/MessageFormatMessage.html[`MessageFormatMessage`] formats its input using https://docs.oracle.com/javase/{java-target-version}/docs/api/java/text/MessageFormat.html[Java's `MessageFormat`].
[WARNING]
====
While `MessageFormatMessage` offers more flexibility compared to <<ParameterizedMessage>>,
the latter is engineered for performance, e.g., it is xref:manual/garbagefree.adoc[garbage-free].
You are recommended to use `ParameterizedMessage` for performance-sensitive setups.
====
[#ObjectMessage]
==== `ObjectMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/ObjectMessage.html[`ObjectMessage`] is a wrapper `Message` implementation to log custom domain model instances.
It formats an input `Object` by calling its `toString()` method.
If the object is found to be extending from <<StringBuilderFormattable>>, it uses `formatTo(StringBuilder)` instead.
`ObjectMessage` can be thought as a convenience for <<ParameterizedMessage>> such that the following message instances are analogous:
* `new ObjectMessage(obj)`
* `new ParameterizedMessage("{}", obj)`
That is,
* They will both be formatted in the same way
* `Message#getParameters()` will return an `Object[]` containing only `obj`
Hence, `ObjectMessage` is intended more as a marker interface to indicate the single value it encapsulates.
[#ReusableObjectMessage]
[NOTE]
====
link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableObjectMessage.html[`ReusableObjectMessage`] provides functionally equivalent to <<ObjectMessage>>, plus methods to replace its content to enable xref:manual/garbagefree.adoc[].
When garbage-free logging is enabled, xref:manual/api.adoc#loggers[loggers] will use this instead of <<ObjectMessage>>.
====
[#ParameterizedMessage]
==== `ParameterizedMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/ParameterizedMessage.html[`ParameterizedMessage`] accepts a formatting pattern containing `{}` placeholders and a list of arguments.
It formats the message such that each `{}` placeholder in the pattern is replaced with the corresponding argument.
[#ReusableParameterizedMessage]
[NOTE]
====
link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableParameterizedMessage.html[`ReusableParameterizedMessage`] provides functionally equivalent to <<ParameterizedMessage>>, plus methods to replace its content to enable xref:manual/garbagefree.adoc[].
When garbage-free logging is enabled, xref:manual/api.adoc#loggers[loggers] will use this instead of <<ParameterizedMessage>>.
====
[#SimpleMessage]
==== `SimpleMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/SimpleMessage.html[`SimpleMessage`] encapsulates a `String` or `CharSequence` that requires no formatting.
[#ReusableSimpleMessage]
[NOTE]
====
link:../javadoc/log4j-api/org/apache/logging/log4j/message/ReusableSimpleMessage.html[`ReusableSimpleMessage`] provides functionally equivalent to <<SimpleMessage>>, plus methods to replace its content to enable xref:manual/garbagefree.adoc[].
When garbage-free logging is enabled, xref:manual/api.adoc#loggers[loggers] will use this instead of <<SimpleMessage>>.
====
[#StringFormattedMessage]
==== `StringFormattedMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/StringFormattedMessage.html[`StringFormattedMessage`] accepts a https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/Formatter.html#syntax[format string] and a list of arguments.
It formats the message using https://docs.oracle.com/javase/{java-target-version}/docs/api/java/lang/String.html#format(java.lang.String,%20java.lang.Object...)[`java.lang.String#format()`].
[WARNING]
====
While `StringFormattedMessage` offers more flexibility compared to <<ParameterizedMessage>>,
the latter is engineered for performance, e.g., it is xref:manual/garbagefree.adoc[garbage-free].
You are recommended to use `ParameterizedMessage` for performance-sensitive setups.
====
[#ThreadDumpMessage]
==== `ThreadDumpMessage`
If a link:../javadoc/log4j-api/org/apache/logging/log4j/message/ThreadDumpMessage.html[`ThreadDumpMessage`] is logged, Log4j generates stack traces for all threads.
These stack traces will include any held locks.
[#collection-structured]
=== Structured types
Log4j strives to provide top of the class support for *structured logging*.
It complements xref:manual/layouts.adoc#structured-logging[structured layouts] with message types allowing users to create structured messages effectively resulting in an end-to-end structured logging experience.
This section will introduce the predefined structured message types.
.What is *structured logging*?
[%collapsible]
====
include::partial$manual/structured-logging.adoc[]
====
[#MapMessage]
==== `MapMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/MapMessage.html[`MapMessage`] is a `Message` implementation that models a Java `Map` with `String`-typed keys and values.
*It is an ideal generic message type for passing structured data.*
`MapMessage` implements link:../javadoc/log4j-api/org/apache/logging/log4j/message/MultiformatMessage.html[`MultiformatMessage`] to facilitate encoding of its content in multiple formats.
It supports following formats:
[%header,cols="1m,5"]
|===
|Format |Description
|XML |format as XML
|JSON |format as JSON
|JAVA |format as `Map#toString()` (the default)
|JAVA_UNQUOTED |format as `Map#toString()`, but without quotes
|===
Some appenders handle ``MapMessage``s differently when there is no layout:
* JMS Appender converts to a JMS `javax.jms.MapMessage`
* xref:manual/appenders.adoc#JDBCAppender[JDBC Appender] converts to values in an `SQL INSERT` statement
* xref:manual/appenders.adoc#NoSQLAppenderMongoDB[MongoDB NoSQL provider] converts to fields in a MongoDB object
[#MapMessage-JsonTemplateLayout]
===== JSON Template Layout
xref:manual/json-template-layout.adoc[] has a specialized handling for ``MapMessage``s to properly encode them as JSON objects.
[#StructuredDataMessage]
==== `StructuredDataMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/StructuredDataMessage.html[`StructuredDataMessage`] formats its content in a way compliant with https://datatracker.ietf.org/doc/html/rfc5424#section-6[the Syslog message format described in RFC 5424].
[#StructuredDataMessage-Rfc5424Layout]
===== RFC 5424 Layout
`StructuredDataMessage` is mostly intended to be used in combination with xref:manual/layouts.adoc#RFC5424Layout[RFC 5424 Layout], which has specialized handling for ``StructuredDataMessage``s.
By combining two, users can have complete control on how their message is encoded in a way compliant with RFC 5424, while RFC 5424 Layout will make sure the rest of the information attached to the log event is properly injected.
[#StructuredDataMessage-JsonTemplateLayout]
===== JSON Template Layout
Since `StructuredDataMessage` extends from <<MapMessage>>, which xref:manual/json-template-layout.adoc[] has a specialized handling for, ``StructuredDataMessage``s will be properly encoded by JSON Template Layout too.
[#performance]
== Performance
As explained in xref:usage[], `SimpleMessage` and `ParameterizedMessage` instances are created indirectly while interacting with `Logger` methods; `info()`, `error()`, etc.
In a modern JVM, the allocation cost difference between these `Message` instances and plain ``String`` objects is marginal.
If you observe this cost to be significant enough for your use case, you can enable xref:manual/garbagefree.adoc[].
This will effectively cause `Message` instances to be recycled and avoid creating pressure on the garbage collector.
In such a scenario, if you also have custom message types, consider implementing <<StringBuilderFormattable>> and introducing a message recycling mechanism.
[#extending]
== Extending
If <<collection,predefined message types>> fall short of addressing your needs, you can extend from the link:../javadoc/log4j-api/org/apache/logging/log4j/message/Message.html[`Message`] interface to either create your own message types or make your domain models take control of the message formatting.
.Example custom message class
[%collapsible]
====
.Snippet from {antora-examples-url}/manual/messages/CustomMessageExample.java[`CustomMessageExample.java`]
[source,java,indent=0]
----
include::example$manual/messages/CustomMessageExample.java[tag=loginFailure]
----
<1> Extending from both `Message` and <<StringBuilderFormattable>> interfaces
<2> Formats the message directly into a `StringBuilder`
<3> `getFormattedMessage()` reuses `formatTo()`
====
[#format-type]
=== Format type
The link:../javadoc/log4j-api/org/apache/logging/log4j/message/Message.html[`Message`] interface supports the notion of _format_ (e.g., JSON, XML) through its `getFormat()` method of return type `String`.
Layouts leverage this mechanism to encode a message in a particular format.
For instance, when xref:manual/json-template-layout.adoc[] figures out that `getFormat()` of a `Message` returns `JSON`, it injects the `Message#getFormattedMessage()` output as is without quoting it.
This way a message implementation can communicate its support for a particular encoding.
If you want to support multiple formats, extend from <<MultiformatMessage>>, and optionally from <<MultiFormatStringBuilderFormattable>>, instead.
[#marker-interfaces]
=== Marker interfaces
There are certain Log4j API interfaces that you can _optionally_ extend from in your `Message` implementations to enable associated features:
[#LoggerNameAwareMessage]
==== `LoggerNameAwareMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/LoggerNameAwareMessage.html[`LoggerNameAwareMessage`] is a marker interface with a `setLoggerName(String)` method.
This method will be called during event construction to pass the associated `Logger` to the `Message`.
[#MultiformatMessage]
==== `MultiformatMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/MultiformatMessage.html[`MultiformatMessage`] extends from `Message` to support multiple <<format-type,format types>>.
For example, see {project-github-url}/tree/2.x/log4j-api/src/main/java/org/apache/logging/log4j/message/MapMessage.java[`MapMessage.java`] extending from `MultiformatMessage` to support multiple formats; XML, JSON, etc.
[#MultiFormatStringBuilderFormattable]
==== `MultiFormatStringBuilderFormattable`
link:../javadoc/log4j-api/org/apache/logging/log4j/util/MultiFormatStringBuilderFormattable.html[`MultiFormatStringBuilderFormattable`] extends <<StringBuilderFormattable>> to support multiple <<format-type,format types>>.
[#StringBuilderFormattable]
==== `StringBuilderFormattable`
Many xref:manual/layouts.adoc[layouts] recycle ``StringBuilder``s to encode log events xref:manual/garbagefree.adoc[without generating garbage], and this effectively results in significant xref:manual/performance.adoc[performance] benefits.
link:../javadoc/log4j-api/org/apache/logging/log4j/util/StringBuilderFormattable.html[`StringBuilderFormattable`] is the primary interface facilitating the formatting of objects to a `StringBuilder`.
[#TimestampMessage]
==== `TimestampMessage`
link:../javadoc/log4j-api/org/apache/logging/log4j/message/TimestampMessage.html[`TimestampMessage`] provides a `getTimestamp()` method that will be called during log event construction to determine the instant instead of using the current timestamp.
`Message` implementations that want to control the timestamp of the log event they are encapsulated in, they can extend from `TimestampMessage`.