This is an automated email from the ASF dual-hosted git repository. vy pushed a commit to branch doc/2.x/extending in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit df1813d2c1079a7bdbe436a90a6361b68b29b636 Merge: 34eb9f036e 204d825129 Author: Volkan Yazıcı <[email protected]> AuthorDate: Tue Jun 25 10:35:58 2024 +0200 Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending # Conflicts: # src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc .mvn/extensions.xml | 2 +- .mvn/wrapper/maven-wrapper.properties | 4 +- .../manual/customloglevels/LevelExample.java | 49 ++++ .../manual/customloglevels/custom/log4j2.json | 34 --- .../manual/customloglevels/custom/log4j2.xml | 28 -- .../manual/customloglevels/custom/log4j2.yaml | 37 --- .../manual/customloglevels/filtering/log4j2.json | 24 -- .../customloglevels/filtering/log4j2.properties | 24 -- .../manual/customloglevels/filtering/log4j2.xml | 21 -- .../examples/manual/customloglevels/log4j2.json | 41 +++ .../customloglevels/{custom => }/log4j2.properties | 23 +- .../{filtering/logback.xml => log4j2.xml} | 38 +-- .../customloglevels/{filtering => }/log4j2.yaml | 20 +- src/site/antora/modules/ROOT/nav.adoc | 2 + src/site/antora/modules/ROOT/pages/log4j-jul.adoc | 196 ++++++++++++++ .../antora/modules/ROOT/pages/log4j-to-jul.adoc | 38 +++ .../modules/ROOT/pages/manual/customloglevels.adoc | 289 +++++++++++++-------- .../modules/ROOT/pages/manual/installation.adoc | 8 +- .../ROOT/partials/manual/levels-log4j-to-jul.adoc | 43 +++ .../systemproperties/properties-log4j-jul.adoc | 20 +- src/site/resources/.htaccess | 3 +- 21 files changed, 618 insertions(+), 326 deletions(-) diff --cc src/site/antora/modules/ROOT/examples/manual/customloglevels/LevelExample.java index 0000000000,ceb92caaea..ceb92caaea mode 000000,100644..100644 --- a/src/site/antora/modules/ROOT/examples/manual/customloglevels/LevelExample.java +++ b/src/site/antora/modules/ROOT/examples/manual/customloglevels/LevelExample.java diff --cc src/site/antora/modules/ROOT/examples/manual/customloglevels/log4j2.json index 0000000000,e29890d90c..e29890d90c mode 000000,100644..100644 --- a/src/site/antora/modules/ROOT/examples/manual/customloglevels/log4j2.json +++ b/src/site/antora/modules/ROOT/examples/manual/customloglevels/log4j2.json diff --cc src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc index 42423e751a,b197e3dc63..3496c96b72 --- a/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc +++ b/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc @@@ -23,19 -22,43 +22,43 @@@ Using levels, you can filter out less i Log4j contains following predefined levels: - [%header,cols="1m,1"] + .Standard log levels + [%header,cols="1,1m",id=standard-log-levels] |=== - |Name |Priority - |OFF |0 - |FATAL |100 - |ERROR |200 - |WARN |300 - |INFO |400 - |DEBUG |500 - |TRACE |600 - |ALL |`Integer.MAX_VALUE` + | Name | Priority + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#OFF[`OFF`]<<dont-use-in-code,[see note]>> + | 0 + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#FATAL[`FATAL`] + | 100 + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#ERROR[`ERROR`] + | 200 + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#WARN[`WARN`] + | 300 + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#INFO[`INFO`] + | 400 + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#DEBUG[`DEBUG`] + | 500 + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#TRACE[`TRACE`] + | 600 + + | link:../javadoc/log4j-api/org/apache/logging/log4j/Level#ALL[`ALL`]<<dont-use-in-code,[see note]>> + | Integer.MAX_VALUE |=== + [IMPORTANT,id=dont-use-in-code] + ==== + The `OFF` and `ALL` levels are special: they should not be used to fish-tag log events. + -Log4j implementations, such as Log4j Core, can use `OFF` in their configuration files to disable all log statements and `ALL` to enabled them all. ++Log4j API implementations, such as Log4j Core, can use `OFF` in their configuration files to disable all log statements and `ALL` to enabled them all. + ==== + A level is composed of a case-sensitive name and a *priority* (of type `int`), which is used to define an order while comparing two. Priority can be used in several contexts to express a filtering capability, for instance: @@@ -48,165 -71,207 +71,207 @@@ Predefined levels are available for Log [#usage] == [[StandardLoggerInterface]] Usage - You can specify the log level while using `Logger` in several ways: + To assign a level to a log event you can use one of the variants of the + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#log(org.apache.logging.log4j.Level,org.apache.logging.log4j.Marker,org.apache.logging.log4j.message.Message)[`Logger.log(..)`] + and + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#atLevel(org.apache.logging.log4j.Level)[`Logger.atLevel(Level)`] + methods: - [source,java] + [source,java,indent=0] ---- - LOGGER.info("Hello, {}!", userName); // <1> - LOGGER.log(Level.INFO, "Hello, {}!", userName); // <2> -include::example$manual/customlevels/LevelExample.java[tag=standard] ++include::example$manual/customloglevels/LevelExample.java[tag=standard] ---- - <1> Using `Logger#info()` to log a message at `INFO` level - <2> Using `Logger#log()` to log a message and specifying the `INFO` level explicitly - [#DefiningLevelsInCode] - === Custom log levels + The `Logger` interface also contains shorthand methods that always log at a specified log level: - Users can programmatically define custom levels using link:../javadoc/log4j-api/org/apache/logging/log4j/Level.html#forName(java.lang.String,int)[the `Level.forName()` method]: + .Shorthand `Logger` methods + [%header,cols="1m,3m"] + |=== + | Effective level | Shorthand methods - [source,java] - ---- - public final class CustomLogLevel { + | FATAL + | link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#fatal(org.apache.logging.log4j.Marker,org.apache.logging.log4j.message.Message)[Logger.fatal(..)], + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#atFatal()[Logger.atFatal()] - public static final Level VERBOSE = Level.forName("VERBOSE", 550); // <1> + | ERROR + | link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#error(org.apache.logging.log4j.Marker,org.apache.logging.log4j.message.Message)[Logger.error(..)], + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#atError()[Logger.atError()] - } - ---- - <1> Creating a custom level with name `VERBOSE` and priority 550 + | WARN + | link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#warn(org.apache.logging.log4j.Marker,org.apache.logging.log4j.message.Message)[Logger.warn(..)], + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#atWarn()[Logger.atWarn()] - Once defined, you can log messages at this level by calling the `Logger#log()` method and passing the custom log level: + | INFO + | link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#info(org.apache.logging.log4j.Marker,org.apache.logging.log4j.message.Message)[Logger.info(..)], + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#atInfo()[Logger.atInfo()] - [source,java] - ---- - public class PurchaseOrder { + | DEBUG + | link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#debug(org.apache.logging.log4j.Marker,org.apache.logging.log4j.message.Message)[Logger.debug(..)], + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#atDebug()[Logger.atDebug()] - private static final Logger LOGGER = LogManager.getLogger(); + | TRACE + | link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#trace(org.apache.logging.log4j.Marker,org.apache.logging.log4j.message.Message)[Logger.trace(..)], + link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html#atTrace()[Logger.atTrace()] - public PurchaseOrder(String id) { - LOGGER.log(CustomLogLevel.VERBOSE, "Creating purchase order with ID `{}`", id); // <1> - // ... - } + |=== - // ... + By using shorthand methods, you can rewrite the example above as: - } + [source,java,indent=0] + ---- -include::example$manual/customlevels/LevelExample.java[tag=shorthand] ++include::example$manual/customloglevels/LevelExample.java[tag=shorthand] ---- - <1> Logging with the created custom level - [#config] - == Configuration + [#level-selection] + === Which level to use? - Levels can be used in various ways in a configuration file. - We will explain some important ones from multiple logging implementations. + [CAUTION] + ==== + While Log4j API defines a set of standard levels, it does not define the purpose of these levels. + Many different conventions on which log levels to use coexist in the industry. + When in doubt, you should ask your teammates about the convention used at your company. + ==== - [#config-core] - === Log4j Core + Most log level usage conventions divide log levels into two categories: - Log4j Core, the reference implementation of Log4j API, has extensive support for levels. - It allows both <<config-core-filter,basic level-based filtering>> and <<DefiningLevelsInConfiguration,custom log levels>>. + * the most severe log levels (e.g. `FATAL`, `ERROR` and `WARN`) are used to inform the system administrator about a problem in the Java application that needs to be fixed. + The more severe the problem, the more severe the log level. + + + Log events with these levels should be used sparingly and should allow the system administrator to fix the problem. - [#config-core-filter] - ==== Basic filtering + * the less severe log levels (e.g. `INFO`, `DEBUG`, `TRACE`) provide context that allow a system administrator or developer to diagnose the reason of an application failure. + The most severe of them describe events that concern the whole application, while the less severe describe events that are interesting for a single sub-system. - Filtering on levels for loggers is a pretty common example: + [#DefiningLevelsInCode] + === Custom log levels - [tabs] - ==== - XML:: - + - .Snippet from an example {antora-examples-url}/manual/customloglevels/filtering/log4j2.xml[`log4j2.xml`] configuring level-filtered loggers - [source,xml] - ---- - include::example$manual/customloglevels/filtering/log4j2.xml[lines=14..19,indent=0] - ---- + While most Java logging APIs adopt the same set of standard logging levels, some logging APIs, such as xref:log4j-jul.adoc#default-level-conversions[JUL] + and external logging systems, such as + https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1[Syslog] + and + https://opentelemetry.io/docs/specs/otel/logs/data-model/#displaying-severity[OpenTelemetry] + support additional logging levels that can not be mapped to the standard ones. - JSON:: - + - .Snippet from an example {antora-examples-url}/manual/customloglevels/filtering/log4j2.json[`log4j2.json`] configuring level-filtered loggers - [source,xml] - ---- - include::example$manual/customloglevels/filtering/log4j2.json[lines=9..22,indent=0] - ---- + To improve interoperability between logging systems, Log4j API supports custom log levels that can be defined using the + link:../javadoc/log4j-api/org/apache/logging/log4j/Level.html#forName(java.lang.String,int)[`Level.forName()`] + method: - YAML:: - + - .Snippet from an example {antora-examples-url}/manual/customloglevels/filtering/log4j2.yaml[`log4j2.yaml`] configuring level-filtered loggers - [source,xml] + [source,java,indent=0] ---- - include::example$manual/customloglevels/filtering/log4j2.yaml[lines=24..31,indent=0] -include::example$manual/customlevels/LevelExample.java[tag=custom-definition] ++include::example$manual/customloglevels/LevelExample.java[tag=custom-definition] ---- - Properties:: - + - .Snippet from an example {antora-examples-url}/manual/customloglevels/filtering/log4j2.properties[`log4j2.properties`] configuring level-filtered loggers - [source,xml] + Custom log levels can be used in your code with the usual `Logger.log(..)` and `Logger.atLevel(Level)` methods: + + [source,java,indent=0] ---- - include::example$manual/customloglevels/filtering/log4j2.properties[lines=21..24] -include::example$manual/customlevels/LevelExample.java[tag=custom] ++include::example$manual/customloglevels/LevelExample.java[tag=custom] ---- + + [#implementation-support] + == Implementation support + + All logging implementations support filtering of log events, based on their log level, but the number of available log levels varies between implementations. + + [WARNING] + ==== + While most logging implementations support <<standard-log-levels,standard log levels>>, custom log levels are only supported by Log4j Core (and the EOL Log4j 1). + To ensure independence from a specific logging implementation you should restrict your log statements to **standard** log levels. + + If you use custom log levels as a fish-tagging technique, you can use alternative + xref:manual/api.adoc#fish-tagging[fish-tagging features] + such as + xref:manual/markers.adoc[], + which are supported by multiple logging implementations. ==== - <1> Logs of level `INFO` or higher severity (i.e., `WARN`, `ERROR`, `FATAL`) are allowed for `com.mycompany` package - <2> Logs of level `ERROR` or higher severity (i.e., `FATAL`) are allowed for the rest [#DefiningLevelsInConfiguration] - ==== Custom log levels - - Log4j Core, the reference implementation of Log4j API, requires a custom level to be defined first, before it can be used in a configuration file. - To facilitate this, the `CustomLevel` configuration element is used to define a custom level. - Internally it calls the same `Level.forName()` method discussed in <<DefiningLevelsInCode>>. + === Log4j Core - The following example shows a configuration that defines the `VERBOSE` custom log level and uses it to filter log events sent to the console. + The Log4j Core implementation fully supports both standard and custom levels. + Similarly to the <<DefiningLevelsInCode,Log4j API usage>>, custom levels must be defined in a configuration file before they can be used. + You can do it using + xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-config-CustomLevelConfig[`CustomLevel`] + configuration elements: [tabs] ==== XML:: + - .Snippet from an example {antora-examples-url}/manual/customloglevels/custom/log4j2.xml[`log4j2.xml`] configuring custom log levels [source,xml] ---- - include::example$manual/customloglevels/custom/log4j2.xml[lines=17..26,indent=0] -include::example$manual/customlevels/log4j2.xml[lines=1;18..-1] ++include::example$manual/customloglevels/log4j2.xml[lines=1;18..-1] ---- JSON:: + - .Snippet from an example {antora-examples-url}/manual/customloglevels/custom/log4j2.json[`log4j2.json`] configuring custom log levels [source,xml] ---- - include::example$manual/customloglevels/custom/log4j2.json[lines=13..32,indent=0] -include::example$manual/customlevels/log4j2.json[] ++include::example$manual/customloglevels/log4j2.json[] ---- YAML:: + - .Snippet from an example {antora-examples-url}/manual/customloglevels/custom/log4j2.yaml[`log4j2.yaml`] configuring custom log levels - [source,xml] + [source,yaml] ---- - include::example$manual/customloglevels/custom/log4j2.yaml[lines=27..37,indent=0] -include::example$manual/customlevels/log4j2.yaml[lines=17..-1] ++include::example$manual/customloglevels/log4j2.yaml[lines=17..-1] ---- Properties:: + - .Snippet from an example {antora-examples-url}/manual/customloglevels/custom/log4j2.properties[`log4j2.properties`] configuring custom log levels - [source,xml] + [source,properties] ---- - include::example$manual/customloglevels/custom/log4j2.properties[lines=24..30] -include::example$manual/customlevels/log4j2.properties[lines=17..-1] ++include::example$manual/customloglevels/log4j2.properties[lines=17..-1] ---- ==== - <1> Defining the `VERBOSE` custom log level - <2> Only events of `VERBOSE` level or higher severity are sent to the console - [#config-logback] - === Logback + <1> All the available xref:manual/layouts.adoc[] support printing levels. + In the case of + xref:manual/pattern-layout.adoc[] + you can use a xref:manual/pattern-layout.adoc#converter-level[`%p` or `%level`] pattern. + <2> Loggers support a xref:manual/configuration.adoc#logger-attributes-level[`level`] configuration attribute to filter log events. + <3> A xref:manual/configuration.adoc#appenderref-attributes-level[`level`] attribute is also available in appender references. + <4> Custom levels must be defined before they can be used. + <5> Custom levels can be used anywhere a standard level can be used. - {logback-url}[Logback] can be configured as follows to define level-filtered loggers: + [#slf4j-implementations] + === SLF4J implementations (Logback) - .Snippet from an example {antora-examples-url}/manual/customloglevels/filtering/logback.xml[`logback.xml`] configuring level-filtered loggers - [source,xml] - ---- - include::example$manual/customloglevels/filtering/logback.xml[lines=29..32,indent=0] - ---- + Since SLF4J only supports five log levels (`ERROR`, `WARN`, `INFO`, `DEBUG` and `TRACE`) and does not support custom log levels, + Log4j API levels are converted according to the following table: + + .Log4j to SLF4J level conversion + [%header,cols="1m,1m,1m"] + |=== + | Log4j level priority | Log4j standard levels | SLF4J Level + + | 0 < priority < 300 + | FATAL, ERROR + | https://www.slf4j.org/api/org/slf4j/event/Level.html#ERROR[ERROR] + + | 300 ≤ priority < 400 + | WARN + | https://www.slf4j.org/api/org/slf4j/event/Level.html#WARN[WARN] + + | 400 ≤ priority < 500 + | INFO + | https://www.slf4j.org/api/org/slf4j/event/Level.html#INFO[INFO] + + | 500 ≤ priority < 600 + | DEBUG + | https://www.slf4j.org/api/org/slf4j/event/Level.html#DEBUG[DEBUG] + + | 600 ≤ priority + | TRACE + | https://www.slf4j.org/api/org/slf4j/event/Level.html#TRACE[TRACE] + + |=== + + [#jul] + === JUL (`java.util.logging`) + + Similarly to Log4j API, `java.util.logging` also supports custom log levels, but the current + xref:log4j-to-jul.adoc[] implementation does not take advantage of them. + The conversion of between Log4j log levels and JUL levels is performed accordingly to the following table: + + include::partial$manual/levels-log4j-to-jul.adoc[]
