Separating Log4J application logging from the server.log in JBoss EAP
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 6
- 7
- Log4j / slf4j / custom logging API deployed with application.
log4j.xml
orlogj.properties
configuration- Per application loggging files
Issue
- Application logging going to
server.log
whenlog4j.xml
is packaged in our application. - Messages are not logged in
server.log
. - I would like to separate application logging configuration file outside the JBoss configuration
-
My logging isn't working correctly, and I'm seeing messages like:
16:17:03,188 INFO [stdout] (Finalizer) log4j: Finalizing appender named [myAppender1]. 16:17:03,189 INFO [stdout] (Finalizer) log4j: Finalizing appender named [myAppender2].
-
logging-profile not working in domain mode
-
Is it possible to create the separate log file for each application where
app1.war
andapp2.war
containssame package name
?app1.war --> app1.log app2.war --> app2.log
-
No logging from EJBs and Servlets packaged in the EAR . We've tried putting the following jboss-deployment-structure.xml within the EJB's
META-INF
folder with no success: - Exclude JBoss Logging Subsystem for Deployments.
- How do we configure logging to use our logging APIs.
Resolution
There are several steps involved in this, and it's important that each step is followed correctly, or this will not work. The high level steps are::
- Package a copy of
log4j.jar
in your deployment - Add the system property
-Dorg.jboss.as.logging.per-deployment=false
'Ref' - Create a
jboss-deployment-structure.xml
to excludeorg.apache.log4j
from your deployment and all subdeployments. - Explicitly initialize your Log4J configuration using a
PropertyConfigurator
orDOMConfigurator
in your application.
Package log4j.jar
in your application along with your Log4J configuration file (log4j.xml
/ log4j.properties
) in the classpath (which would be in the root of a jar or in /WEB-INF/classes
for a war).
Remember, "all subdeployments" means that if you have an EAR that there should be a jboss-deployment-structure.xml at the EAR level, and then another one inside of each WAR or any other type of nested deployment you have inside of that EAR.
Add the system property -Dorg.jboss.as.logging.per-deployment=false
, which disables the deployer which scans for the logging configuration files in your deployment. This will prevent JBoss from trying to create a log context for your deployment.
If your logging configuration file has a different name than the standard ones (e.g. log4j.xml
, log4j.properties
), you will then need to initialize your logging framework in your code e.g. a ServletContextInitialzer
if you're using a WAR:
import java.io.IOException;
import java.net.URL;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import org.apache.log4j.xml.DOMConfigurator;
@javax.servlet.annotation.WebListener
public class TestListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
URL log4jXml = Thread.currentThread().getContextClassLoader().getResource("/my-log4j.xml");
if(log4jXml == null)
throw new IllegalStateException("my-log4j.xml not found");
DOMConfigurator.configure(log4jXml);
}
public void contextDestroyed(ServletContextEvent event) {
}
}
You will also need to declare an exclusion (as shown below) in order to not use the logging frameworks already provided by JBoss. Create a jboss-deployment-structure.xml
in the root of your top level deployment in WEB-INF
for wars or META-INF
for all other types. Here is an example of what you'd put in the META-INF
folder of an EAR:
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="org.apache.log4j" />
</exclusions>
</deployment>
<sub-deployment name="myapp.war">
<exclusions>
<module name="org.apache.log4j" />
</exclusions>
</sub-deployment>
</jboss-deployment-structure>
The same file would be put in the WEB-INF
folder of a WAR without the <sub-deployment>
element. Note that if you have multiple WARs embedded in an EAR, you must configure <sub-deployment/>
for each WAR. You can not use a wildcard "*" for it. See Knowledge article #179153
A working example is attached as separate-logfile-example.zip
. This sample application is based on ejb-in-ear quickstart project. Similarly, log4j2 example is attached as separate-logfile-log4j2-example.zip
. This sample application is based on ejb-in-war quickstart project. Extract the archive and follow the instructions described in README.txt
.
To create a separate log file for each server instance running in domain mode we can use jboss.node.name
in log4j.xml/log4j.properties file, and while starting server instance use -Djboss.node.name=Node_Name
property.
log4j.appender.myFileAppender.File=/valid/path/${jboss.node.name}.log
<param name="File" value="${jboss.server.log.dir}/${jboss.node.name}.log"/>
Root Cause
By default JBoss will look in deployments at deployment time for one of the following logging configuration files: log4.properties,
log4j.xml, jboss-log4j.xml
, jboss-logging.properties
or logging.properties
. If JBoss finds one, then it will create a log context for the deployment using the packaged configuration file. This means that if you were using Log4J as your logging framework before and want to use your appenders, then it will "just work", and you can have your application log to its own file.
Diagnostic Steps
-
If you see these messages:
16:17:03,188 INFO [stdout] (Finalizer) log4j: Finalizing appender named [myAppender1]. 16:17:03,189 INFO [stdout] (Finalizer) log4j: Finalizing appender named [myAppender2].
This means that you are using the Log4J implementation from JBoss, not from your deployment. Make sure you closely followed the instructions regarding the exclusion of the
org.apache.log4j
module from your deployment and all subdeployments.To know for sure, you can try executing the following code:
System.out.println(Logger.class.getPackage().getImplementationTitle()); System.out.println(Logger.class.getPackage().getImplementationVendor()); System.out.println(Logger.class.getPackage().getImplementationVersion());
This should output something like this if you're using Red Hat's implementation:
[stdout] log4j-jboss-logmanager [stdout] JBoss by Red Hat [stdout] 1.0.2.Final-redhat-1
-
You do not require separate "jboss-deployment-structure.xml" for each individual war/jar files packaged inside a ear, instead consolidate all of them into a single "jboss-deployment-structure.xml" within the
EAR/META-INF
folder as explained above .
Attachments
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Comments