diff --git a/antora-playbook.yaml b/antora-playbook.yaml index beaabee98cb..6bafbcabee0 100644 --- a/antora-playbook.yaml +++ b/antora-playbook.yaml @@ -88,10 +88,10 @@ ui: .doc pre { font-size: 0.7rem; } .doc .colist { font-size: 0.75rem; } /* Tab header fonts aren't rendered good, adjusting the font weight: */ - .tablist > ul li { font-weight: 500; } + .tablist > ul li { font-weight: 500; } /* `page-toclevels` greater than 4 are not supported by Antora UI, patching it: */ .toc .toc-menu li[data-level="4"] a { - padding-left: 2.75rem + padding-left: 2.75rem; } /* Replace the default highlight.js color for strings from red (unnecessarily signaling something negative) to green: */ .hljs-string { diff --git a/src/site/antora/modules/ROOT/nav.adoc b/src/site/antora/modules/ROOT/nav.adoc index abcc645e4e2..b7789787fdc 100644 --- a/src/site/antora/modules/ROOT/nav.adoc +++ b/src/site/antora/modules/ROOT/nav.adoc @@ -22,43 +22,46 @@ ** link:{logging-services-url}/security[Security] ** xref:thanks.adoc[Thanks] -.Learn -* xref:manual/index.adoc[] -** xref:manual/installation.adoc[] -** xref:manual/architecture.adoc[] -** xref:manual/migration.adoc[] -** xref:manual/api.adoc[] -*** xref:manual/logbuilder.adoc[] -*** xref:manual/flowtracing.adoc[] -*** xref:manual/markers.adoc[] -*** xref:manual/eventlogging.adoc[] -*** xref:manual/messages.adoc[] -*** xref:manual/thread-context.adoc[] -*** xref:manual/scoped-context.adoc[] -*** xref:manual/resource-logger.adoc[] -** xref:manual/configuration.adoc[] -** xref:manual/usage.adoc[] -** xref:manual/cloud.adoc[] -** xref:manual/lookups.adoc[] -** xref:manual/appenders.adoc[] -** xref:manual/layouts.adoc[] -*** xref:manual/json-template-layout.adoc[] -** xref:manual/filters.adoc[] -** xref:manual/async.adoc[] -** xref:manual/garbagefree.adoc[] -** xref:manual/extending.adoc[] -** xref:manual/plugins.adoc[] -** xref:manual/customconfig.adoc[] -** xref:manual/customloglevels.adoc[] -** xref:manual/jmx.adoc[] -** xref:manual/logsep.adoc[] -** xref:manual/performance.adoc[] -* xref:plugin-reference.adoc[Plugin reference] -* xref:javadoc.adoc[Java API reference] -* xref:articles.adoc[Articles] +.Resources * xref:faq.adoc[F.A.Q.] +* xref:5min.adoc[] * xref:development.adoc[] +.xref:manual/index.adoc[] +* xref:manual/installation.adoc[] +* xref:manual/architecture.adoc[] +* xref:manual/migration.adoc[] +* xref:manual/api.adoc[] +** xref:manual/logbuilder.adoc[] +** xref:manual/flowtracing.adoc[] +** xref:manual/markers.adoc[] +** xref:manual/eventlogging.adoc[] +** xref:manual/messages.adoc[] +** xref:manual/thread-context.adoc[] +** xref:manual/scoped-context.adoc[] +** xref:manual/resource-logger.adoc[] +* xref:manual/configuration.adoc[] +* xref:manual/usage.adoc[] +* xref:manual/cloud.adoc[] +* xref:manual/lookups.adoc[] +* xref:manual/appenders.adoc[] +* xref:manual/layouts.adoc[] +** xref:manual/json-template-layout.adoc[] +* xref:manual/filters.adoc[] +* xref:manual/async.adoc[] +* xref:manual/garbagefree.adoc[] +* xref:manual/extending.adoc[] +* xref:manual/plugins.adoc[] +* xref:manual/customconfig.adoc[] +* xref:manual/customloglevels.adoc[] +* xref:manual/jmx.adoc[] +* xref:manual/logsep.adoc[] +* xref:manual/performance.adoc[] + +.References +* xref:plugin-reference.adoc[Plugin reference] +* xref:javadoc.adoc[Java API reference] + .Components * xref:log4j-api.adoc[] * xref:log4j-1.2-api.adoc[] diff --git a/src/site/antora/modules/ROOT/pages/5min.adoc b/src/site/antora/modules/ROOT/pages/5min.adoc new file mode 100644 index 00000000000..864dca105b1 --- /dev/null +++ b/src/site/antora/modules/ROOT/pages/5min.adoc @@ -0,0 +1,476 @@ +//// + 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. +//// + += Learn Log4j in 5 minutes! + +You need a crash course on Log4j? +You are at the right place! + +[#what] +== What is logging and Log4j? + +Logging is the action of publishing diagnostics information at certain points of a program execution: + +[source,java] +---- +private void truncateTable(String tableName) { + System.out.format("[WARN] Truncating table `%s`!%n", tableName); + db.truncate(tableName); +} +---- + +This provides observability into an application's runtime. (See {logging-services-url}/what-is-logging.html[What is logging?] page for a longer read.) + +But we can do way better than a `printf()` statement! + +* Enhance the message with additional information (timestamp, class & method name, line number, host, severity, etc.) +* Write the message in a different way, using a different **layout** (CSV, JSON, etc.) +* Write the message to a different medium, using a different **appender** (file, socket, database, queue, etc.) +* Write only some of the messages, using a **filter** (e.g. filter by severity, content, etc.) + +Log4j is versatile, industrial-grade Java logging framework delivering all these and more in one product. +It is essentially composed of a **logging API** and its **implementation**: + +Log4j API:: +The logging API your code (programmatically) logs through. +This needs to be available at compile-time and no configuration is needed. + +Log4j Core:: +The logging implementation which is responsible for filtering, routing, encoding, and appending log events. +This needs to be available at runtime and configured by the user. + +[#logging] +== How do I log using Log4j? + +Add the `log4j-api` dependency to your application: + +[tabs] +==== +Maven:: ++ +[source,xml,subs="+attributes"] +---- + + + + + + org.apache.logging.log4j + log4j-bom + {log4j-core-version} + import + pom + + + + + + + org.apache.logging.log4j + log4j-api + + + + +---- + +Gradle:: ++ +[source,groovy,subs="+attributes"] +---- +dependencies { + implementation platform('org.apache.logging.log4j:log4j-bom:{log4j-core-version}') + implementation 'org.apache.logging.log4j:log4j-api' +} +---- +==== + +And start logging: + +[source,java] +---- +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +public class DbTableService { + + private static final Logger LOGGER = LogManager.getLogger(); // <1> + + public void truncateTable(String tableName) throws IOException { + LOGGER.warn("truncating table `{}`", tableName); // <2> + db.truncate(tableName); + } + +} +---- +<1> This is a thread-safe, reusable `Logger` instance. +The associated class will be captured at initialization – no need for a `getLogger(DbTableService.class)`. +<2> The parameter placeholders `{}` in the message will be automatically replaced with the value of `tableName` and the generated **log event** will be enriched with **level** (i.e., `WARN`), timestamp, class & method name, line number, and several other information. + +Make sure to log exceptions that have diagnostics value: + +[source,java] +---- +LOGGER.warn("truncating table `{}`", tableName); +try { + db.truncate(tableName); +} catch (IOException exception) { + LOGGER.error("failed truncating table `{}`", tableName, exception); // <1> + throw new IOException("failed truncating table: " + tableName, exception); +} +---- +<1> Notice the `error()` method? +Yup, the level is set to `ERROR`. ++ +What about the `exception` in the last argument? +Wait a second! +There is one placeholder in the format (i.e., `{}`), but there are two parameters passed in arguments: `tableName` and `exception`! +What the heck? +Yep, you guessed it right! +Log4j API will attach the last extra argument of type `Throwable` in a separate field to the generated log event. + +[#pitfalls] +=== Common pitfalls + +There are several widespread bad practices. +Let's try to walk through the most common ones. + +[#pitfal-toString] +==== Don't use `toString()` + +* [ ] `Object#toString()` is redundant in arguments ++ +[source,java] +---- +/* BAD! */ LOGGER.info("userId: {}", userId.toString()); +---- + +* [x] Underlying message type and layout will deal with arguments ++ +[source,java] +---- +/* GOOD */ LOGGER.info("userId: {}", userId); +---- + +[#pitfall-exception] +==== Pass exception as the last extra argument + +Using `Throwable#printStackTrace()` or `Throwable#getMessage()` while logging? +Please, don't! + +* [ ] Don't call `Throwable#printStackTrace()`. +This not only circumvents the logging, but can also leak sensitive information! ++ +[source,java] +---- +/* BAD! */ exception.printStackTrace(); +---- + +* [ ] Don't use `Throwable#getMessage()`. +This prevents the log event from getting enriched with the exception. ++ +[source,java] +---- +/* BAD! */ LOGGER.info("failed", exception.getMessage()); +/* BAD! */ LOGGER.info("failed for user ID `{}`: {}", userId, exception.getMessage()); +---- + +* [ ] This bloats the log message with duplicate exception message ++ +[source,java] +---- +/* BAD! */ LOGGER.info("failed for user ID `{}`: {}", userId, exception.getMessage(), exception); +---- + +* [x] Pass exception as the last extra argument ++ +[source,java] +---- +/* GOOD */ LOGGER.error("failed", exception); +/* GOOD */ LOGGER.error("failed for user ID `{}`", userId, exception); +---- + +[#pitfal-concat] +==== Don't use string concatenation + +If you are using `String` concatenation while logging, you are doing something very wrong and dangerous! + +* [ ] Circumvents the handling of arguments by message type and layout. +More importantly, this code is prone to attacks! +Imagine `userId` being provided by user with the following content: +`placeholders for non-existing args to trigger failure: {} {} \{dangerousLookup}` ++ +[source,java] +---- +/* BAD! */ LOGGER.info("failed for user ID: " + userId); +---- + +* [x] Use message parameters ++ +[source,java] +---- +/* GOOD */ LOGGER.info("failed for user ID `{}`", userId); +---- + +[#config-app] +== How do I configure Log4j to run my **application**? + +Your code logs through a logging API. +So your dependencies and their dependencies too. +While deploying your application, you need to provide a **logging implementation** along with its configuration to consume all generated log events. + +[IMPORTANT] +==== +Are you implementing not an **application**, but a **library**? +Please skip to the xref:#config-lib[] instead. +==== + +Add the `log4j-core` **runtime** dependency to your application: + +[tabs] +==== +Maven:: ++ +[source,xml,subs="+attributes"] +---- + + + + + + + + + org.apache.logging.log4j + log4j-core + runtime + + + + + org.apache.logging.log4j + log4j-layout-template-json + runtime + + + + + org.apache.logging.log4j + log4j-slf4j2-impl + runtime + + + + + +---- + +Gradle:: ++ +[source,groovy,subs="+attributes"] +---- +dependencies { + + // Assuming you already have the `implementation platform(...)` entry for `log4j-bom` + + // The logging implementation (i.e., Log4j Core) + runtimeOnly 'org.apache.logging.log4j:log4j-core' // <1> + + // Log4j JSON-encoding support + runtimeOnly 'org.apache.logging.log4j:log4j-layout-template-json' // <1> + + // SLF4J-to-Log4j bridge // <2> + runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl' // <1> + +} +---- +==== +<1> Note that the logging implementation and bridges are only needed at runtime! +<2> SLF4J is another widely used logging API. +`log4j-slf4j2-impl` forwards SLF4J calls to Log4j API, which effectively gets processed by Log4j Core too. + +Now it is time to configure Log4j and instruct how the log events should be routed. +Save the following XML document to `src/**main**/resources/log4j2.xml`: + +.An example `src/**main**/resources/log4j2.xml` +[source,xml] +---- + + + + + + + + + + + + + + + + + +---- +<1> xref:manual/appenders.adoc[Appenders] are responsible for writing log events to console, file, socket, database, etc. +<2> xref:manual/appenders.adoc#ConsoleAppender[Console Appender] is used to write logs to the console. +<3> xref:manual/json-template-layout.adoc[JSON Template Layout] is used to encode log events in JSON. +<4> Log events generated by classes in the `com.mycompany` package (incl. its subpackages) and that are of level `INFO` and higher (i.e., `WARN`, `ERROR`, `FATAL`) will be consumed. +<5> Unless specified otherwise, log events of level `WARN` and and higher will be consumed. +<6> Unless specified otherwise, log events will be forwarded to the `console` appender defined earlier. + +You are strongly advised to use a different Log4j configuration for tests. +Continue to xref:#config-test[] + +[#config-lib] +== How do I configure Log4j for my **library**? + +Unlike applications, libraries should be logging implementation agnostic. +That is, **libraries should log through a logging API, but leave the decision of the logging implementation to the application**. +That said, libraries need a logging implementation while running their tests. + +[IMPORTANT] +==== +Are you implementing not a **library**, but an **application**? +Please skip to the xref:#config-app[] instead. +==== + +Add the `log4j-core` **test** dependency to your library: + +[tabs] +==== +Maven:: ++ +[source,xml,subs="+attributes"] +---- + + + + + + + + + org.apache.logging.log4j + log4j-core + test + + + + + org.apache.logging.log4j + log4j-slf4j2-impl + test + + + + + +---- + +Gradle:: ++ +[source,groovy,subs="+attributes"] +---- +dependencies { + + // Assuming you already have the `implementation platform(...)` entry for `log4j-bom` + + // The logging implementation (i.e., Log4j Core) + testOnly 'org.apache.logging.log4j:log4j-core' // <1> + + // SLF4J-to-Log4j bridge // <2> + testOnly 'org.apache.logging.log4j:log4j-slf4j2-impl' // <1> + +} +---- +==== +<1> Note that the logging implementation and bridges are only needed for tests! +<2> SLF4J is another widely used logging API. +`log4j-slf4j2-impl` forwards SLF4J calls to Log4j API, which effectively gets processed by Log4j Core too. + +Next, you need a `src/**test**/resources/log4j2-test.xml`. +See xref:#config-test[] + +[#config-test] +== How do I configure Log4j for tests? + +For tests, prefer a human-readable layout with increased verbosity. +Save the following XML document to `src/**test**/resources/log4j2-test.xml`: + +.An example `src/**test**/resources/log4j2-test.xml` +[source,xml] +---- + + + + + + + + + + + + + + + + + +---- +<1> xref:manual/layouts.adoc#PatternLayout[Pattern Layout] is used for a human-readable layout. +<2> Increased logging verbosity for the `com.mycompany` package. + +[#next] +== What is next? + +Installation:: +While shared dependency management snippets should get you going, it can also be challenging depending on your use case. +Are you dealing with a Spring Boot application? +Is it running in a Java EE container? +Do you need to take into account other logging APIs such as JUL, JPL, JCL, etc.? +See xref:manual/installation.adoc[] for the complete installation guide. + +Configuration:: +Log4j can be configured in several ways in various file formats (XML, JSON, Properties, and YAML). +See the xref:manual/configuration.adoc[] page for details. + +Appenders & Layouts:: +Log4j contains several xref:manual/appenders.adoc[appenders] and xref:manual/layouts.adoc[layouts] to compose a configuration that best suit your needs. + +Performance:: +Do you want to get the best performance out of your logging system? +Make sure to check out the xref:manual/performance.adoc[] page. + +Architecture:: +Want to learn more about loggers, contexts, and how these are all wired together? +See the xref:manual/architecture.adoc[] page. + +Support:: +Confused? +Having problem while setting up Log4j? +See the {logging-services-url}/support.html[Support] page. diff --git a/src/site/antora/modules/ROOT/pages/download.adoc b/src/site/antora/modules/ROOT/pages/download.adoc index 0666d48ac91..27dbfa84425 100644 --- a/src/site/antora/modules/ROOT/pages/download.adoc +++ b/src/site/antora/modules/ROOT/pages/download.adoc @@ -21,3 +21,13 @@ You can manually download all published Log4j distributions, verify them, and se * Are you looking for **the Log4j installation instructions**? Proceed to xref:manual/installation.adoc[]. * Are you looking for the list of changes associated with a particular release? Proceed to xref:release-notes.adoc[]. + +[#older] +== Older releases + +Are you looking for old versions of Log4j? +While we recommend to always use the latest version, you can find the older versions here: + +* {logging-services-url}/1.x/[Log4j 1.x (End of Life, Java 1.4)] +* {logging-services-url}/2.3.x/[Log4j 2.3.x (Java 6)] +* {logging-services-url}/2.12.x/[Log4j 2.12.x (Java 7)] diff --git a/src/site/antora/modules/ROOT/pages/index.adoc b/src/site/antora/modules/ROOT/pages/index.adoc index 879c5ab4cc7..2ccc92b10ca 100644 --- a/src/site/antora/modules/ROOT/pages/index.adoc +++ b/src/site/antora/modules/ROOT/pages/index.adoc @@ -23,11 +23,12 @@ The project is actively maintained by a {logging-services-url}/team-list.html[te [#shortcuts] == Shortcuts -- xref:manual/installation.adoc[How can I add Log4j artifacts to my Maven/Ivy/Gradle project?] -- xref:manual/usage.adoc[How can I use the Log4j API?] + +- xref:5min.adoc[] +- xref:manual/installation.adoc[How can I install Log4j? Which dependencies are needed?] - xref:manual/configuration.adoc[How can I configure my `log4j2.xml`?] - xref:release-notes.adoc[Where are the release notes?] -- {logging-services-url}/support[**I need help!**] +- {logging-services-url}/support.html[**I need help!**] [#features] == Features @@ -60,26 +61,3 @@ Extensibility:: Log4j contains a fully-fledged xref:manual/plugins.adoc[plugin support] that users can leverage to extend its functionality. You can easily add your own components (layouts, appenders, filters, etc.) or customizing existing ones (e.g., adding new directives to the xref:manual/layouts.adoc#PatternLayout[Pattern] or xref:manual/json-template-layout.adoc#extending[JSON Template Layout]). Check out the xref:manual/extending.adoc[Extending Log4j] page. - -[#requirements] -== Requirements - -Log4j 2 runtime requires a minimum of Java 8. -Older versions of Java are supported by previous releases. - -[#older-releases] -== Older releases - -Are you looking for old versions of Log4j? -While we recommend to always use the latest version, you can find the older versions here: - -* {logging-services-url}/1.x/[Log4j 1.x (End of Life, Java 1.4)] -* {logging-services-url}/2.3.x/[Log4j 2.3.x (Java 6)] -* {logging-services-url}/2.12.x/[Log4j 2.12.x (Java 7)] - -[#compat] -== Compatibility - -The `log4j-1.2-api` module provides compatibility for applications using the Log4j 1 logging methods. -Log4j 2 also provides support for Log4j 1 configuration files. -See xref:manual/migration.adoc#ConfigurationCompatibility[Log4j 2 compatibility with Log4j 1] for more information. diff --git a/src/site/antora/modules/ROOT/pages/manual/installation.adoc b/src/site/antora/modules/ROOT/pages/manual/installation.adoc index c2ac9f13c9d..1e027bb7450 100644 --- a/src/site/antora/modules/ROOT/pages/manual/installation.adoc +++ b/src/site/antora/modules/ROOT/pages/manual/installation.adoc @@ -391,6 +391,8 @@ Since version `1.3.0` https://commons.apache.org/proper/commons-logging/[Apache You can enforce the version of a transitive dependency using the dependency management mechanism appropriate to your build tool: +[tabs] +==== Maven:: Maven users should add an entry to the `` section of their POM file: + @@ -408,6 +410,7 @@ Maven users should add an entry to the `` section of their Gradle:: + Gradle users should refer to the https://docs.gradle.org/current/userguide/platforms.html#sub:using-platform-to-control-transitive-deps[Using a platform to control transitive versions] of the Gradle documentation. +==== [#impl-core-bridge-jboss-logging] ===== Installing JBoss Logging-to-Log4j bridge @@ -484,13 +487,15 @@ log4j2.xml:: + https://logging.apache.org/xml/ns/log4j-config-2.xsd"> - + + + - + @@ -504,7 +509,10 @@ log4j2.json:: "Configuration": { "Appenders": { "Console": { - "name": "CONSOLE" + "name": "CONSOLE", + "PatternLayout": { + "pattern": "%d [%t] %5p %c{1.} - %m%n" // <1> + } } }, "Loggers": { @@ -527,6 +535,8 @@ Configuration: Appenders: Console: name: CONSOLE + PatternLayout: + pattern: "%d [%t] %5p %c{1.} - %m%n" # <1> Loggers: Root: level: INFO @@ -540,11 +550,14 @@ log4j2.properties:: ---- appender.0.type = Console appender.0.name = CONSOLE +appender.0.layout = PatternLayout # <1> +appender.0.layout.pattern = %d [%t] %5p %c{1.} - %m%n rootLogger.level = INFO rootLogger.appenderRef.0.ref = CONSOLE ---- ==== +<1> While xref:manual/layouts.adoc#PatternLayout[Pattern Layout] is a good first choice and preferable for tests, we recommend using a structured format such as xref:manual/json-template-layout.adoc[] for production deployments. In order to use these formats, the following additional dependencies are required: