| //// |
| 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 |
| |
| https://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. |
| //// |
| = Frequently Asked Questions |
| :toc: |
| |
| ''' |
| |
| [#missing_core] |
| == I'm seeing this error "Unable to locate a logging implementation, using SimpleLogger". What is wrong? |
| |
| You have the log4j-api-2.x jar file in your classpath but you still need |
| to add the log4j-core-2.x jar to the classpath. (Also, it looks like you |
| are using an old version of Log4j 2. You may want to upgrade.) |
| |
| [#which_jars] |
| == Which JAR files do I need? |
| |
| You need at least the log4j-api-2.x and the log4j-core-2.x jar files. |
| |
| The other jars are necessary if your application calls the API of |
| another logging framework and you want to route logging calls to the |
| Log4j 2 implementation. |
| |
| image:images/whichjar-2.x.png[Diagram showing which JARs correspond to |
| which systems] |
| |
| You can use the log4j-to-slf4j adapter jar when your application calls |
| the Log4j 2 API and you want to route logging calls to a SLF4J |
| implementation. |
| |
| image:images/whichjar-slf4j-2.x.png[Diagram showing the dependency flow |
| to use Log4j 2 API with SLF4J] |
| |
| Some of the Log4j components have features with optional dependencies. |
| The component page will have more detail. For example, the |
| link:log4j-core/index.html[log4j-core component page] has an outline of |
| which log4j-core features have external dependencies. |
| |
| [#exclusions] |
| == How do I exclude conflicting dependencies? |
| |
| There are several scenarios where you may end up with conflicting |
| dependencies, especially transitively included ones. The following table |
| shows for each Log4j dependency on the left (implicit groupId of |
| `org.apache.logging.log4j`), the following dependencies on the right can |
| be safely excluded (given in the format `groupId:artifactId`). |
| |
| [cols="4*m",options="header"] |
| |=== |
| |Log4j Dependency |
| 3+|Dependencies to Exclude |
| |
| |log4j-1.2-api |
| |log4j:log4j |
| 2+|org.slf4j:log4j-over-slf4j |
| |
| |log4j-core |
| |log4j:log4j |
| |ch.qos.logback:logback-core |
| |org.apache.logging.log4j:log4j-to-slf4j |
| |
| |log4j-jcl |
| 3+|org.slf4j:jcl-over-slf4j |
| |
| |log4j-jul |
| 3+|org.slf4j:jul-to-slf4j |
| |
| |log4j-slf4j-impl |
| |org.apache.logging.log4j:log4j-to-slf4j |
| 2+|ch.qos.logback:logback-core |
| |=== |
| |
| Using Apache Maven, dependencies can be globally excluded in your |
| project like so: |
| |
| [source,xml] |
| ---- |
| <dependencies> |
| <dependency> |
| <groupId>log4j</groupId> |
| <artifactId>log4j</artifactId> |
| <version>1.2.17</version> |
| <scope>provided</scope> |
| </dependency> |
| </dependencies> |
| ---- |
| |
| Dependencies can be explicitly excluded for specific dependencies as |
| well. For example, to use a project with Log4j 2 instead of Log4j 1.x: |
| |
| [source,xml,subs="attributes,specialchars"] |
| ---- |
| <dependencies> |
| <dependency> |
| <groupId>com.example</groupId> |
| <artifactId>example-project</artifactId> |
| <version>1.0</version> |
| <exclusions> |
| <exclusion> |
| <groupId>log4j</groupId> |
| <artifactId>log4j</artifactId> |
| </exclusion> |
| <exclusion> |
| <groupId>org.slf4j</groupId> |
| <artifactId>slf4j-log4j12</artifactId> |
| </exclusion> |
| </exclusions> |
| </dependency> |
| <dependency> |
| <groupId>org.apache.logging.log4j</groupId> |
| <artifactId>log4j-core</artifactId> |
| <version>{Log4jReleaseVersion}</version> |
| </dependency> |
| <dependency> |
| <groupId>org.apache.logging.log4j</groupId> |
| <artifactId>log4j-slf4j-impl</artifactId> |
| <version>{Log4jReleaseVersion}</version> |
| </dependency> |
| <dependency> |
| <groupId>org.apache.logging.log4j</groupId> |
| <artifactId>log4j-1.2-api</artifactId> |
| <version>{Log4jReleaseVersion}</version> |
| </dependency> |
| </dependencies> |
| ---- |
| |
| Dependencies can be globally excluded in Gradle like so: |
| |
| [source,gradle] |
| ---- |
| configurations { |
| all*.exclude group: 'log4j', module: 'log4j' |
| } |
| ---- |
| |
| The equivalent Gradle config for the above Maven exclusion would look |
| like: |
| |
| [source,gradle,subs=attributes] |
| ---- |
| dependencies { |
| compile('com.example:example-project:1.0') { |
| exclude group: 'log4j', module: 'log4j' |
| exclude group: 'org.slf4j', module: 'slf4j-log4j12' |
| } |
| compile('org.apache.logging.log4j:log4j-core:{Log4jReleaseVersion}') |
| compile('org.apache.logging.log4j:log4j-slf4j-impl:{Log4jReleaseVersion}') |
| compile('org.apache.logging.log4j:log4j-1.2-api:{Log4jReleaseVersion}') |
| } |
| ---- |
| |
| [#config_location] |
| == How do I specify the configuration file location? |
| |
| By default, Log4j looks for a configuration file named *log4j2.xml* (not |
| log4j.xml) in the classpath. |
| |
| You can also specify the full path of the configuration file with this |
| system property: `-Dlog4j.configurationFile=path/to/log4j2.xml` |
| |
| That property can also be included in a classpath resource file named |
| `log4j2.component.properties`. |
| |
| Web applications can specify the Log4j configuration file location with |
| a servlet context parameter. See |
| http://logging.apache.org/log4j/2.x/manual/webapp.html#ContextParams[this |
| section] of the Using Log4j 2 in Web Applications manual page. |
| |
| [#config_from_code] |
| == How do I configure log4j2 in code without a configuration file? |
| |
| Starting with version 2.4, Log4j 2 provides an |
| link:manual/customconfig.html[API for programmatic configuration] The |
| new |
| link:log4j-core/apidocs/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.html[`ConfigurationBuilder` |
| API] allows you to create Configurations in code by constructing |
| component definitions without requiring you to know about the internals |
| of actual configuration objects like Loggers and Appenders. |
| |
| [#reconfig_from_code] |
| == How do I reconfigure log4j2 in code with a specific configuration file? |
| |
| See the below example. Be aware that this LoggerContext class is not |
| part of the public API so your code may break with any minor release. |
| |
| [source,java] |
| ---- |
| // import org.apache.logging.log4j.core.LoggerContext; |
| |
| LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false); |
| File file = new File("path/to/a/different/log4j2.xml"); |
| |
| // this will force a reconfiguration |
| context.setConfigLocation(file.toURI()); |
| ---- |
| |
| [#shutdown] |
| == How do I shut down log4j2 in code? |
| |
| Normally there is no need to do this manually. Each `LoggerContext` |
| registers a shutdown hook that takes care of releasing resources when |
| the JVM exits (unless system property `log4j.shutdownHookEnabled` is set |
| to `false`). Web applications should include the log4j-web module in |
| their classpath which disables the shutdown hook but instead cleans up |
| log4j resources when the web application is stopped. |
| |
| However, if you need to manually shut down Log4j, you can do so as in |
| the below example. Note that there is an optional parameter for |
| specifying which `LoggerContext` to shut down. |
| |
| [source,java] |
| ---- |
| import org.apache.logging.log4j.LogManager; |
| |
| // ... |
| |
| LogManager.shutdown(); |
| ---- |
| |
| [#config_sep_appender_level] |
| == How do I send log messages with different levels to different |
| appenders? You don’t need to declare separate loggers to achieve this. |
| You can set the logging level on the `AppenderRef` element. |
| |
| [source,xml] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <Configuration status="WARN"> |
| <Appenders> |
| <File name="file" fileName="app.log"> |
| <PatternLayout> |
| <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern> |
| </PatternLayout> |
| </File> |
| <Console name="STDOUT" target="SYSTEM_OUT"> |
| <PatternLayout pattern="%m%n"/> |
| </Console> |
| </Appenders> |
| <Loggers> |
| <Root level="trace"> |
| <AppenderRef ref="file" level="DEBUG"/> |
| <AppenderRef ref="STDOUT" level="INFO"/> |
| </Root> |
| </Loggers> |
| </Configuration> |
| ---- |
| |
| [#troubleshooting] |
| == How do I debug my configuration? |
| |
| First, make sure you have link:#which_jars[the right jar files] on your |
| classpath. You need at least log4j-api and log4j-core. |
| |
| Next, check the name of your configuration file. By default, log4j2 will |
| look for a configuration file named `log4j2.xml` on the classpath. Note |
| the ``2'' in the file name! (See the |
| link:manual/configuration.html#AutomaticConfiguration[configuration |
| manual page] for more details.) |
| |
| From log4j-2.9 onward:: |
| From log4j-2.9 onward, log4j2 will print all internal logging to the |
| console if system property `log4j2.debug` is defined (with any or no |
| value). |
| |
| Prior to log4j-2.9:: |
| Prior to log4j-2.9, there are two places where internal logging can be |
| controlled: |
| + |
| If the configuration file is found correctly, log4j2 internal status |
| logging can be controlled by setting `<Configuration status="trace">` in |
| the configuration file. This will display detailed log4j2-internal log |
| statements on the console about what happens during the configuration |
| process. This may be useful to trouble-shoot configuration issues. By |
| default the status logger level is WARN, so you only see notifications |
| when there is a problem. |
| + |
| If the configuration file is not found correctly, you can still enable |
| log4j2 internal status logging by setting system property |
| `-Dorg.apache.logging.log4j.simplelog.StatusLogger.level=TRACE`. |
| |
| [#separate_log_files] |
| == How do I dynamically write to separate log files? |
| |
| Look at the |
| http://logging.apache.org/log4j/2.x/manual/appenders.html#RoutingAppender[RoutingAppender]. |
| You can define multiple routes in the configuration, and put values in |
| the `ThreadContext` map that determine which log file subsequent events |
| in this thread get logged to. |
| |
| You can use the `ThreadContext` map value to determine the log file |
| name. |
| |
| [source,xml] |
| ---- |
| <Routing name="Routing"> |
| <Routes pattern="$${ctx:ROUTINGKEY}"> |
| |
| <!-- This route is chosen if ThreadContext has value 'special' for key ROUTINGKEY. --> |
| <Route key="special"> |
| <RollingFile name="Rolling-${ctx:ROUTINGKEY}" fileName="logs/special-${ctx:ROUTINGKEY}.log" |
| filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}-special-%d{yyyy-MM-dd}-%i.log.gz"> |
| <PatternLayout> |
| <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> |
| </PatternLayout> |
| <Policies> |
| <TimeBasedTriggeringPolicy interval="6" modulate="true" /> |
| <SizeBasedTriggeringPolicy size="10 MB" /> |
| </Policies> |
| </RollingFile> |
| </Route> |
| |
| <!-- This route is chosen if ThreadContext has no value for key ROUTINGKEY. --> |
| <Route key="$${ctx:ROUTINGKEY}"> |
| <RollingFile name="Rolling-default" fileName="logs/default.log" |
| filePattern="./logs/${date:yyyy-MM}/default-%d{yyyy-MM-dd}-%i.log.gz"> |
| <PatternLayout> |
| <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> |
| </PatternLayout> |
| <Policies> |
| <TimeBasedTriggeringPolicy interval="6" modulate="true" /> |
| <SizeBasedTriggeringPolicy size="10 MB" /> |
| </Policies> |
| </RollingFile> |
| </Route> |
| |
| <!-- This route is chosen if ThreadContext has a value for ROUTINGKEY |
| (other than the value 'special' which had its own route above). |
| The value dynamically determines the name of the log file. --> |
| <Route> |
| <RollingFile name="Rolling-${ctx:ROUTINGKEY}" fileName="logs/other-${ctx:ROUTINGKEY}.log" |
| filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}-other-%d{yyyy-MM-dd}-%i.log.gz"> |
| <PatternLayout> |
| <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> |
| </PatternLayout> |
| <Policies> |
| <TimeBasedTriggeringPolicy interval="6" modulate="true" /> |
| <SizeBasedTriggeringPolicy size="10 MB" /> |
| </Policies> |
| </RollingFile> |
| </Route> |
| </Routes> |
| </Routing> |
| ---- |
| |
| [#reconfig_level_from_code] |
| == How do I set a logger’s level programmatically? |
| |
| You can set a logger’s level with the class |
| link:log4j-core/apidocs/org/apache/logging/log4j/core/config/Configurator.html[`Configurator`] |
| from Log4j Core. Be aware that the `Configurator` class is not part of |
| the public API. |
| |
| [source,java] |
| ---- |
| import org.apache.logging.log4j.core.config.Configurator; |
| |
| // ... |
| |
| Configurator.setLevel("com.example.Foo", Level.DEBUG); |
| |
| // You can also set the root logger: |
| Configurator.setRootLevel(Level.DEBUG); |
| ---- |
| |
| [#retention] |
| == How do I set my log archive retention policy? How do I delete old log archives? |
| |
| The `DefaultRolloverStrategy` of the Rolling File appender (and Rolling |
| Random Access File appender) supports a |
| link:manual/appenders.html#CustomDeleteOnRollover[Delete] element. |
| |
| Starting at a specified base directory, you can delete all files for |
| which some condition holds true, for example all files that match a |
| given file name pattern and are older than some number of days. More |
| complex conditions are possible, and if the built-in conditions are not |
| sufficient, users can provide custom conditions by creating |
| link:manual/appenders.html#DeletePathCondition[plugin conditions] or by |
| writing a link:manual/appenders.html#ScriptCondition[script condition]. |
| |
| [#api-tradeoffs] |
| == What are the trade-offs of using the Log4j 2 API versus the SLF4J API? |
| |
| The Log4j 2 API and SLF4J have a lot in common. They both share the |
| objective of cleanly separating the logging API from the implementation. |
| We believe that the Log4j 2 API can help make your application more |
| performant while offering more functionality and more flexibility. |
| |
| There may be a concern that using the Log4j 2 API will tightly couple |
| your application to Log4j 2. This is not the case: applications coded to |
| the Log4j 2 API always have the option to use any SLF4J-compliant |
| library as their logging implementation with the log4j-to-slf4j adapter. |
| See the link:#which_jars_log4j-to-slf4j[which jars] FAQ entry for |
| details. |
| |
| There are several advantages to using the Log4j 2 API: |
| |
| * SLF4J forces your application to log Strings. The Log4j 2 API supports |
| logging any CharSequence if you want to log text, but also supports |
| logging any Object as is. It is the responsibility of the logging |
| implementation to handle this object, and we consider it a design |
| mistake to limit applications to logging Strings. |
| * The Log4j 2 API offers support for logging |
| link:manual/messages.html[Message objects]. Messages allow support for |
| interesting and complex constructs to be passed through the logging |
| system and be efficiently manipulated. Users are free to create their |
| own Message types and write custom Layouts, Filters and Lookups to |
| manipulate them. |
| * The Log4j 2 API has support for Java 8 |
| link:manual/api.html#LambdaSupport[lambda expressions]. |
| * The Log4j 2 API has better support for |
| link:manual/garbagefree.html[garbage-free logging]: it avoids creating |
| vararg arrays and avoids creating Strings when logging CharSequence |
| objects. |
| |
| [#gc-free-slf4j] |
| == Is Log4j 2 still garbage-free when I use the SLF4J API? |
| |
| Yes, the log4j-slf4j-impl binding (together with log4j-core) implements |
| the `org.slf4j.Logger` methods to be GC-free. However, bear in mind that |
| there are some limitations: |
| |
| The SLF4J API only offers up to two parameters for a parameterized |
| message. More than that uses varargs which creates a temporary object |
| for the parameter array. The Log4j 2.6 API has methods for up to ten |
| unrolled parameters. |
| |
| Another consideration is that the SLF4J API forces your application to |
| log Strings. Log4j 2 API lets you log any java.lang.CharSequence, and |
| even any Objects. Log4j can log any Object that implements |
| `java.lang.CharSequence` or |
| `org.apache.logging.log4j.util.StringBuilderFormattable` without |
| creating garbage. |
| |
| The |
| http://www.slf4j.org/api/org/slf4j/spi/LocationAwareLogger.html#log(org.slf4j.Marker,%20java.lang.String,%20int,%20java.lang.String,%20java.lang.Object%5B%5D,%20java.lang.Throwable)[`org.slf4j.spi.LocationAwareLogger::log`] |
| method is not yet implemented in a garbage-free manner in the |
| log4j-slf4j-impl binding. It creates a new message object for each call. |
| |
| [#gc-free-domain-object] |
| == How do I log my domain object without creating garbage? |
| |
| One option is to let the domain object implement java.lang.CharSequence. |
| However, for many domain objects it may not be trivial to implement this |
| without allocating temporary objects. |
| |
| An alternative is to implement the |
| `org.apache.logging.log4j.util.StringBuilderFormattable` interface. If |
| an object is logged that implements this interface, its `formatTo` |
| method is called instead of `toString()`. |
| |
| [source,java] |
| ---- |
| package org.apache.logging.log4j.util; |
| public interface StringBuilderFormattable { |
| /** |
| * Writes a text representation of this object into the specified {@code StringBuilder}, |
| * ideally without allocating temporary objects. |
| * |
| * @param buffer the StringBuilder to write into |
| */ |
| void formatTo(StringBuilder buffer); |
| } |
| ---- |
| |
| [#logger-wrapper] |
| == How do I create a custom logger wrapper that shows the correct class, method and line number? |
| |
| Log4j remembers the fully qualified class name (FQCN) of the logger and |
| uses this to walk the stack trace for every log event when configured to |
| print location. (Be aware that logging with location is slow and may |
| impact the performance of your application.) |
| |
| The problem with custom logger wrappers is that they have a different |
| FQCN than the actual logger, so Log4j can’t find the place where your |
| custom logger was called. |
| |
| The solution is to provide the correct FQCN. The easiest way to do this |
| is to let Log4j generate the logger wrapper for you. Log4j comes with a |
| Logger wrapper generator tool. This tool was originally meant to support |
| custom log levels and is documented |
| https://logging.apache.org/log4j/2.x/manual/customloglevels.html#CustomLoggers[here]. |
| |
| The generated logger code will take care of the FQCN. |