Just recently, I needed to take a look at the SLF4J (Simple Logging Facade 4 Java) API, and more specifically, to how it could be employed on WebLogic Server.
Simple Logging Facade for Java
http://www.slf4j.org/
SLF4J follows the Commons-Logging model in that it provides a "Simple Logging Facade" with an API that can be used to insert log messages into application code, without specifying the specific Logging framework that is to be used. The actual work of capturing and emitting the log message is handled by "pluggable" SLF4J binding, which are added at deployment/runtime time (or server start) and handle the actual logging implementation work. There are pre-built bindings for the common logging frameworks such as JDK logging, Log4J, LogBack, as well as a simple Logging implementation that appears to simply print log messages to stdout.
Basic Problem
Having a look at a project that was using SLF4J with WebLogic Server, the question that came up was how could we direct the SLF4J logs into the standard WebLogic Server log facilities.
In it's basic form, with the slf4j-simple-1.6.0.jar binding being used, the SLF4J logs were not consistent with the rest of the WebLogic Server logs.
<Jun 7, 2011 3:22:04 PM CST> <Notice> <WebLogicServer> <BEA-000395> <Following extensions directory contents added to the end of the classpath:
/Users/sbutton/Projects/Domains/wls1035/lib/slf4j-api-1.6.0.jar:/Users/sbutton/Projects/Domains/wls1035/lib/slf4j-simple-1.6.0.jar>
<Jun 7, 2011 3:22:05 PM CST> <Info> <WebLogicServer> <BEA-000377> <Starting WebLogic Server with Java HotSpot(TM) 64-Bit Server VM Version 19.1-b02-334 from Apple Inc.>
<Jun 7, 2011 3:22:05 PM CST> <Info> <Management> <BEA-141107> <Version: WebLogic Server 10.3.5.0 Fri Apr 1 20:20:06 PDT 2011 1398638 >
. . .
. . .
<Jun 7, 2011 3:22:13 PM CST> <Notice> <WebLogicServer> <BEA-000331> <Started WebLogic Admin Server "myserver" for domain "mydomain" running in Development Mode>
<Jun 7, 2011 3:22:13 PM CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to RUNNING>
<Jun 7, 2011 3:22:13 PM CST> <Notice> <WebLogicServer> <BEA-000360> <Server started in RUNNING mode>
14 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] INFO com.oracle.demo.wlsslf4j.TestServlet - *** This is an info: class com.oracle.demo.wlsslf4j.TestServlet
14 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] WARN com.oracle.demo.wlsslf4j.TestServlet - *** This is a warning: class com.oracle.demo.wlsslf4j.TestServlet
14 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] ERROR com.oracle.demo.wlsslf4j.TestServlet - *** This is an error: class com.oracle.demo.wlsslf4j.TestServlet
The question was: without writing a specific WLS binding, is there a way to enable the SLF4J logs to be directed into the WebLogic Server logs so they are consistently formatted and able to be viewed in the WebLogic Server console with the rest of the logs?
One Solution
The solution was quite straightforward in the end, simply by combining two pieces of existing functionality:
1. The SLF4J distribution ships with a binding for JDK logging called slf4j-jdk14-1.6.0.jar. This results in the SLf4J logs being directed into the JDK logging framework.
2. WebLogic Server ships with a JDK logging handler which will pick up log messages emitted from JDK logging framework and direct them into the WebLogic Server logging system.
The weblogic.logging.ServerLoggingHandler is documented here:
http://download.oracle.com/docs/cd/E14571_01/web.1111/e13739/logging_services.htm#CHDBBEIJ
To get it all working, all it required was making the relevant libraries available to WebLogic Server and wiring them together using a logging.properties file.
Copy Libraries into WebLogic Server
SLF4J basically comes as two components. There's the API which is used by applications, and then there's the bridgings that handle the actual production of log messages into the desired form.
To make SLF4J available to WebLogic Server, I employed the simplest way I know - copy them into the domain/lib directory. This has a certain set of limitations in terms of updating versions without a server restart, etc. but it's a really simple way to get things working in the first instance.
sbutton:~/Projects/Domains/wls1035 $ ls -l lib/
total 88
-rw-r--r-- 1 sbutton staff 702 6 Jun 13:15 readme.txt
-rw-r--r-- 1 sbutton staff 25496 7 Jun 15:19 slf4j-api-1.6.0.jar
-rw-r--r-- 1 sbutton staff 8887 7 Jun 15:34 slf4j-jdk14-1.6.0.jar
Create a logging.properties file
The logging.properties file is a standard way to control JDK logging. Since we have directed SLf4J logs into JDK logging framework by making the slf4j-jdk14-1.6.0 binding available, we can configure JDK logging to use the ServerLoggingHandler provided by WebLogic Server, so as to direct its logs into the WebLogic Server logging system.
The JDK logging framework and its configuration options are all well documented, starting from Nov 2001 here:
http://download.oracle.com/javase/1.4.2/docs/guide/util/logging/overview.html
Here is the logging.properties file that was used:
####
# Specify the handlers to create in the root logger
handlers = weblogic.logging.ServerLoggingHandler
# Register handlers for the com.oracle.demo package and its child loggers
com.oracle.demo.handlers = weblogic.logging.ServerLoggingHandler
# Do not send the org.hibernate.validator log messages to the root handler
com.oracle.demo.useParentHandlers = false
# Set the default logging level for the root logger
.level = ALL
com.oracle.demo.level = ALL
# Set the default logging level for new ServerLoggingHandler instances
weblogic.logging.ServerLoggingHandler.level = ALL
To direct the JDK logging framework to use the logging.properties file, the standard System property java.util.logging.config.file is used. With WebLogic Server, this can be easily accomplished by setting the JAVA_OPTIONS System property with the corresponding value.
$ export JAVA_OPTIONS="-Djava.util.logging.config.file=/Users/sbutton/Projects/Domains/wls1035/logging.properties"
Start WebLogic Server and Observe
With the libraries copied into the domain/lib directory, the logging.properties file created and specified as $JAVA_OPTIONS, starting WebLogic Server should now allow the logs created via SLF4J to be directed into the WebLogic Server logging framework. This should let them be seen on stdout in a consistent form with the standard WebLogic Server log messages, as well as via the WebLogic Server console through it's log viewer.
SL4J logs in stdout
<Jun 7, 2011 3:52:01 PM CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to RUNNING>
<Jun 7, 2011 3:52:01 PM CST> <Notice> <WebLogicServer> <BEA-000360> <Server started in RUNNING mode>
<Jun 7, 2011 3:52:07 PM CST> <Warning>
<com.oracle.demo.wlsslf4j.TestServlet> <BEA-000000> <*** This is a warning: class com.oracle.demo.wlsslf4j.TestServlet>
<Jun 7, 2011 3:52:07 PM CST> <Error> <com.oracle.demo.wlsslf4j.TestServlet> <BEA-000000> <*** This is an error: class com.oracle.demo.wlsslf4j.TestServlet>
SL4J logs in WebLogic Server console