Log4j Core Plugins
The log4j-tomcat
artifact contains three Log4j Core plugins that help to split logs between web applications:
-
The Tomcat Context Selector can be used to split loggers into separate logger contexts, one context for each application.
-
The Tomcat Lookup can be used to retrieve the name of the current Tomcat engine, host or context and use it in a Log4j Core configuration file.
-
The Tomcat Context Data Provider injects the name of the current Tomcat engine, host and context into the context data of each event.
Generic installation
The Log4j Core Plugins can be installed in two different ways:
- Global
-
If you use Log4j Core as Tomcat’s logging system, follow the Tomcat JULI to Log4j API bridge installation instructions and add the
log4j-tomcat-3.0.0-beta1.jar
artifact to you$CATALINA_BASE/bin/logging
folder.You can download the artifact from this Maven Central location.
- Web application
-
If you want to add the plugins to a single web application, add this dependency to your dependency management system:
-
Maven
-
Gradle
<dependency> <groupId>eu.copernik</groupId> <artifactId>log4j-tomcat</artifactId> <version>3.0.0-beta1</version> </dependency>
implementation 'eu.copernik:log4j-tomcat:3.0.0-beta1'
-
Tomcat Context Selectors
The Tomcat Context Selectors are a pair
ContextSelector
that splits loggers according to the value of the current context classloader.
The name of the logger contexts is determined as follows:
-
if the context classloader is the classloader of a web application, the name is of the form
/<engine>/<host>/<context>
, where:<engine>
-
The name of the Tomcat Engine container. See Tomcat Engine Container for more details.
<host>
-
The name of the Tomcat Host container. See Tomcat Host Container for more details.
<context>
-
The base file name of the Tomcat Context container. See Tomcat Context Naming for more details.
-
if the context classloader is not the classloader of a web application, the name is
-tomcat
.
Due to the Log4j Core automatic configuration procedure (see Configuration location) you can:
-
Provide a configuration file for a single web application by creating a file named:
log4j2/<engine>/<host>/<context>.<extension>
on the classpath of the application, e.g.
log4j2/Catalina/localhost/app.xml
-
Provide a configuration file for the global Tomcat logger context by creating a
log4j2-tomcat.xml
file.
Loggers used by the libraries in Tomcat’s common classloader will be assigned to the web application that was active when the logger was created. The assignment will be appropriate only if the library uses instance field to store application-specific loggers. Tomcat libraries use instance and static logger fields correctly to differentiate the log statements specific to a web application from the global ones. Most third-party libraries, however, only use static logger fields. The output of those libraries will be assigned to the global logger context or in the worst case scenario to the logger context of the first web application that initialized the library. |
Installation
Using Tomcat Context Selectors only makes sense if you installed the Copernik.eu Log4j Core Plugins globally. In this section, we assume you followed the installation instructions above. |
To use the Tomcat Context Selector, you need to set the
log4j2.contextSelector
Log4j configuration property to one of:
eu.copernik.log4j.tomcat.TomcatContextSelector
-
This selector creates synchronous loggers that append log events to the target resource on the calling thread.
eu.copernik.log4j.tomcat.TomcatAsyncContextSelector
-
This selector creates asynchronous loggers. See Asynchronous Loggers for more details.
The
TomcatAsyncContextSelector
required additional dependencies on the classpath.Add
disruptor-4.0.0.jar
to the$CATALINA_BASE/bin/logging
folder. You can download the artifact from this Maven Central location.
This can be easily achieved, by creating a log4j2.component.properties
file in the $CATALINA_BASE/conf/logging
folder with the following content:
log4j2.contextSelector = eu.copernik.log4j.tomcat.TomcatContextSelector
or
log4j2.contextSelector = eu.copernik.log4j.tomcat.TomcatAsyncContextSelector
See Log4j Property Sources for alternative ways to set a Log4j configuration property.
Tomcat Lookup
Syntax |
where |
---|
The Tomcat Lookup is a Log4j Core Lookup that can be used in configuration files to retrieve parameters of the web application active on the current thread.
The lookup uses the context classloader, so it can be used eagerly (${tomcat:<key>}
) in every value of the configuration file or lazily ($${tomcat:<key>}
) in the configuration attributes that accept runtime evaluation.
See
Runtime Property Substitution
for more details.
The keys supported by the lookup are:
Key | Description |
---|---|
The base name of the current Tomcat Context Container. See Tomcat Context Naming for more details. |
|
Returns the name of the logger that captures all
|
|
The name of the current Tomcat Host Container. See Tomcat Host Container for more details. |
|
Returns the name of the logger that captures all
|
|
The name of the current Tomcat Engine Container. See Tomcat Engine Container for more details. |
|
Returns the name of the logger that captures all
|
|
An alias for See
Using |
|
An alias for See
Using |
|
An alias for See
Using |
Configuration examples
Since the Tomcat Lookup returns For example, we can assign a default value to
Snippet from an example
log4j2.xml file
Snippet from an example
log4j2.json file
Snippet from an example
log4j2.yaml file
The examples below all contain this definition. |
Single configuration file for multiple contexts
If we use Tomcat Context Selector to split the loggers into one logger context per-application, we can still use a single configuration file. To provide a different configuration to each context, we can use the Tomcat Lookup.
The snippet below provides a rolling file appender named after the Tomcat Context, as in the standard configuration file:
-
XML
-
JSON
-
YAML
log4j2.xml
file<RollingFile name="FILE"
filePattern="${logs.dir}/${tomcat:context.name}.%d{yyyy-MM-dd}.log"> (1)
<PatternLayout pattern="${one.line.pattern}"/>
<DirectWriteRolloverStrategy>
<Delete basePath="${logs.dir}">
<IfFileName regex="${tomcat:context.name}\.\d{4}-\d{2}-\d{2}\.log"/>
<IfLastModified age="P90D"/>
</Delete>
</DirectWriteRolloverStrategy>
<TimeBasedTriggeringPolicy/>
</RollingFile>
log4j2.json
file"RollingFile": {
"name": "FILE",
"filePattern": "${logs.dir}/${tomcat:context.name}.%d{yyyy-MM-dd}.log", (1)
"PatternLayout": {
"pattern": "${one.line.pattern}"
},
"DirectWriteRolloverStrategy": {
"Delete": {
"basePath": "${logs.dir}",
"IfFileName": {
"regex": "${tomcat:context.name}\\.\\d{4}-\\d{2}-\\d{2}\\.log"
},
"IfLastModified": {
"age": "P90D"
}
}
},
"TimeBasedTriggeringPolicy": {}
}
log4j2.yaml
fileRollingFile:
name: "FILE"
filePattern: "${logs.dir}/${tomcat:context.name}.%d{yyyy-MM-dd}.log" (1)
PatternLayout:
pattern: "${one.line.pattern}"
DirectWriteRolloverStrategy:
Delete:
basePath: "${logs.dir}"
IfFileName:
regex: "${tomcat:context.name}\.\d{4}-\d{2}-\d{2}\.log"
IfLastModified:
age: "P90D"
TimeBasedTriggeringPolicy: { }
1 | We name the log file after the context name.
For the global logger context we provide the fallback name catalina . |
Single context with dynamic appenders
If we have a single logger context for the entire JVM, we can still split application-specific logs into separate log files. To do that we just need to wrap the example above in a Routing Appender.
-
XML
-
JSON
-
YAML
log4j2.xml
file<Routing name="ROUTING">
<Routes pattern="$${tomcat:context.name}">
<Route>
<RollingFile name="${tomcat:context.name}"
filePattern="${logs.dir}/${tomcat:context.name}.%d{yyyy-MM-dd}.log">
<PatternLayout pattern="${one.line.pattern}"/>
<DirectWriteRolloverStrategy>
<Delete basePath="${logs.dir}">
<IfFileName regex="${tomcat:context.name}\.\d{4}-\d{2}-\d{2}\.log"/>
<IfLastModified age="P90D"/>
</Delete>
</DirectWriteRolloverStrategy>
<TimeBasedTriggeringPolicy/>
</RollingFile>
</Route>
</Routes>
</Routing>
log4j2.json
file"Routing": {
"name": "ROUTING",
"Routes": {
"pattern": "$${tomcat:context.name}",
"Route": {
"RollingFile": {
"name": "${tomcat:context.name}",
"filePattern": "${logs.dir}/${tomcat:context.name}.%d{yyyy-MM-dd}.log",
"PatternLayout": {
"pattern": "${one.line.pattern}"
},
"DirectWriteRolloverStrategy": {
"Delete": {
"basePath": "${logs.dir}",
"IfFileName": {
"regex": "${tomcat:context.name}\\.\\d{4}-\\d{2}-\\d{2}\\.log"
},
"IfLastModified": {
"age": "P90D"
}
}
},
"TimeBasedTriggeringPolicy": {}
}
}
}
}
log4j2.yaml
fileRouting:
name: "ROUTING"
Routes:
pattern: "$${tomcat:context.name}"
Route:
RollingFile:
name: "${tomcat:context.name}"
filePattern: "${logs.dir}/${tomcat:context.name}.%d{yyyy-MM-dd}.log" #
PatternLayout:
pattern: "${one.line.pattern}"
DirectWriteRolloverStrategy:
Delete:
basePath: "${logs.dir}"
IfFileName:
regex: "${tomcat:context.name}\.\d{4}-\d{2}-\d{2}\.log"
IfLastModified:
age: "P90D"
TimeBasedTriggeringPolicy: { }
Tomcat Context Data Provider
If log events from multiple web applications are written to the same target resource, we can tag the events to determine their origin. See Fish tagging for more information.
The Tomcat Context Data Provider uses the Log4j
ContextDataProvider
extension point to inject the key/value pairs below into the context data map of each log event.
Key | Value |
---|---|
The base name of the current Tomcat Context Container. See Tomcat Context Naming for more details. |
|
The name of the current Tomcat Host Container. See Tomcat Host Container for more details. |
|
The name of the current Tomcat Engine Container. See Tomcat Engine Container for more details. |
The Tomcat Context Data Provider is only useful if you installed the Copernik.eu Log4j Core Plugins using the global installation method. The provider must be explicitly enabled by setting the
|
Configuration properties
The Copernik.eu Log4j Core Plugins recognize the following Log4j configuration properties:
log4j2.tomcatContextDataEnabled
Env. variable |
|
---|---|
Type |
|
Default value |
|
If set to true
, the context data map of each log event is enriched by Tomcat-specific properties.
See Tomcat Context Data Provider for more information.