webapp-slf4j-logger is an SLF4J backend that forwards logs to a ServletContext
object.
All log messages are logged using ServletContext#log, allowing a J2EE webapp to send its logs towards the J2EE container logs. This is pretty handy with docker or docker-compose containers, since it will show the webapp logs directly in their logs.
Features:
- zero-config for default functional behaviour (with J2EE annotations enabled, if you're lucky that will be the default, otherwise see below)
- Custom formats (with %date, %level, %logger, %ip, %user, %message)
- Custom format placeholders (using slf4j MDC, aka Mapped Diagnostic Contexts), which can be used to display contextual information like source filename, line and column, etc.
- Email notifications
- Supports session serialization & deserialization
- Per-class log levels
- Errors stack traces stripping
To build the jar:
$ mvn package
To build the javadocs:
$ mvn javadoc:javadoc
If your J2EE container is complient with the 3.0 servlet API, then you just have to include webapp-slf4j-logger.jar in your WEB-INF/lib
directory or in your pom.xml
:
<dependency>
<groupId>com.republicate</groupId>
<artifactId>webapp-slf4j-logger</artifactId>
<version>1.6</version>
<scope>runtime</scope>
</dependency>
But make sure that metadata-complete
attribute of the root <web-app>
tag is absent or set to false
in your webapp descriptior (the web.xml
file).
Configuration parameters are read:
- from context parameters, with the configuration namespace prefix:
<context-param>
<param-name>webapp-slf4j-logger.***parameter***</param-name>
<param-value>***value***</param-value>
</context-param>
- from the
/WEB-INF/logger.properties
file, without the configuration namespace prefix:
***parameter***=***value***
- from the JVM system properties, with the configuration namespace prefix
The latter takes ther precedence and overwrites the former.
Here's an example /WEB-INF/logger.properties
file:
level = trace
level.org.apache.velocity = warn
level.org.apache.commons = error
format = %logger [%level] [%ip] %message @%file:%line:%column
notification = error:smtp:mail.foo.com:25:[email protected]:[email protected]
Possible values for log levels are (case insensitive) trace
, debug
, info
, warn
,
error
, following the standard slf4j levels.
The default log level is info
, and can be changed in the /WEB-INF/logger.properties
file using:
level = debug
or in the webapp descriptor:
<context-param>
<param-name>webapp-slf4j-logger.level</param-name>
<param-value>debug</param-value>
</context-param>
The default enabled level is INFO.
Per-class log levels are set as well using context parameters, using webapp-slf4j-logger..level - for instance, setting the foo.bar
logger to info
is done as follow:
level = debug
Or:
<context-param>
<param-name>webapp-slf4j-logger.level.foo.bar</param-name>
<param-value>info</param-value>
</context-param>
The format can be specified with a context parameter, as a sequence of placeholders and literal text.
<context-param>
<param-name>webapp-slf4j-logger.format</param-name>
<param-value>%logger [%level] [%ip] %message</param-value>
</context-param>
Or:
format = %logger [%level] [%ip] %message
Placeholders begin with '%' and must only contain alpha-numeric characters.
Predefined placeholders:
- %date - the timestamp, formatted as "YYYY-MM-DD HH:mm:ss,sss".
- %level, %Level, %LEVEL - the level in lowercase, standard case or uppercase (and left-padded to five characters).
- %logger - the name of the logger.
- %ip - the IP address of the current HTTP request - note that the logger tries hard to get the real IP address when behind proxies.
- %user - the name of the currently logged HTTP user
- %message - the actual log message string
Custom placeholders must correspond to existing MDC tags. Check the IPTagFilter.java class to see an example.
The default format is:
format = %logger [%level] [%ip] %message
(it doesn't include %date, as the date will usually be added by the J2EE container, nor does it add a terminal \n, as the container will take care of it).
The logger can be configured to send an email if severity is beyond a certain level (typically, warning or error). The configuration parameter is of the form:
notification = *level*:*from_address*:*to_address*
The server, port, user and password are expected to be found in the environment as:
SMTP_HOST
SMTP_PORT
SMTP_USER
SMTP_PASSWORD
The starttls
protocol is expected.
Example:
notification = warn:from@address:to@address
You can also set this parameter to false
to disable the notifications. Compared to just removing the parameter, it's useful if you are generating your webapp descriptor from, let say, filtered maven resources.
The logger can strip out standard strack trace elements (the ones that come from Java itself, the J2EE container or the JDBC driver) so that the displayed stack traces only contain the pith and marrow code locations, the ones that correspond to your application code.
This is enabled by default in 1.6. It's configured with:
stripper = *empty*/'none'/'false' | 'default' | *coma separated list of packages prefixes*
The default filtered out packages are:
- java
- javax
- com.mysql
- org.apache
- org.codehaus
- org.eclipse
- org.postgresql
- sun
For instance:
stripper = java.lang., com.foo.
Package names aren't supposed to end with a period, if they don't, com.foo
will also strip out com.foobar
.
TODO - allow inclusions and exclusions with +some.package,-some.other.package
, starting from the default set.
The logger uses an annotated ServletContextListener which should be picked up by the servlet container at initialization, provided that you did not set the metadata-complete=true
attribute in the root <webapp>
tag, so all you have to do is have the webapp-slf4j-logger
present in WEB-INF/lib
.
Note that if the order in which servlet context listeners are initialized is important to you (like if you want to use the logger from within another servlet context listener), then you should explicitely declare all listeners, including the com.republicate.slf4j.impl.ServletContextLoggerListener
, in your webapp descriptor as detailed below.
If your J2EE container is not complient with servlet API 3.0, you have to add to web.xml
:
<listener>
<listener-class>com.republicate.slf4j.impl.ServletContextLoggerListener</listener-class>
</listener>
And if you want to enable the %ip format tag, you'll also have to add the following filter:
<filter>
<filter-name>webapp-slf4j-logger-ip-tag-filter</filter-name>
<filter-class>com.republicate.slf4j.impl.IPTagFilter</filter-class>
</filter>
with its mapping:
<filter-mapping>
<filter-name>webapp-slf4j-logger-ip-tag-filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Some containers, Tomcat at least, will not search for servlet-3.0 annotations in a certain number of jars, among which all slf4j-* jars...