How to configure logging in JBoss EAP 6.2

Writeup of what I did in late January 2017 in order to configure logging in JBoss EAP 6.2.

Based on my travails, when it comes to logging in JBoss EAP6.2 there are three distinct options:

The above options are discussed in the respective sections below. Note that JBoss EAP 6.2+ and JBoss EAP 7.x use Log4j 1.2.16 (source).

just use System.out.println

This is the simplest approach of all. Under this approach all of your output is given by System.out.println statements which are going to find their way into the server.log file (e.g. in standalone/log/server.log). There is however a catch: Apparently there is a bug in JBoss to the effect that if a log4j.xml or logging.properties file is present on the classpath (typically in WEB-INF/classes) then these System.out.println logging statement will not be logged on the console, server.log, or test.log. They will simply vanish. According to a JBoss developer I spoke to this bug was fixed in EAP 6.2.3.

I also posted a question in SO about this mysterious disappearence of System.out.println messages and the same JBoss developer confirmed the issue (more or less) and suggested a workaround that might not require removal of logging.properties files. Namely, that I "just add a jboss-deployment-descriptor.xml and exclude the logging subsystem from processing your deployment". I tried that I solution as well but it didn't work.

use log4j and rely on the logging subsystem provided by JBoss

As noted, JBoss EAP 6.2+ and JBoss EAP 7.x use Log4j so you can directly use logger.info and it works out of the box. Just be sure to compile your sources against a compatible version of Log4j (in other words pull the right Ivy dependency). Also, you only need the Log4j jars for the compilation stage. In both this and the next approach there is no reason (in fact you shouldn't) bundle the Log4j jar in the deployment WAR (e.g. in WEB-INF/lib). The output of all statements ending up in both the console and file server.log. You do not need to configure any additional logging in standalone-full.xml. Below is what I've used which is only trivially modified with respect to the default configuration bundled in EAP 6.2.0:

<subsystem xmlns="urn:jboss:domain:logging:1.3"> <console-handler name="CONSOLE"> <level name="INFO"/> <formatter> <pattern-formatter pattern="%K{level}%d{MM-dd HH:mm:ss} %-5p [%c] (%t) %s%E%n"/> </formatter> </console-handler> <periodic-rotating-file-handler name="FILE" autoflush="true"> <formatter> <pattern-formatter pattern="%d{MM-dd HH:mm:ss} %-5p [%c] (%t) %s%E%n"/> </formatter> <file relative-to="jboss.server.log.dir" path="server.log"/> <suffix value=".yyyy-MM-dd"/> <append value="true"/> </periodic-rotating-file-handler> <logger category="com.arjuna"> <level name="WARN"/> </logger> <logger category="org.apache.tomcat.util.modeler"> <level name="WARN"/> </logger> <logger category="org.jboss.as.config"> <level name="DEBUG"/> </logger> <logger category="sun.rmi"> <level name="WARN"/> </logger> <logger category="jacorb"> <level name="WARN"/> </logger> <logger category="jacorb.config"> <level name="ERROR"/> </logger> <root-logger> <level name="INFO"/> <handlers> <handler name="CONSOLE"/> <handler name="FILE"/> </handlers> </root-logger> </subsystem>

In this approach, since there is no log4j.xml file bundled with our WAR (see next section), we have no problem with the System.out.println statements as well, i.e. they all appear both in the console and server.xml

If we also want our logging to end up in a separate file as well we can issue the following CLI commands (source), e.g. for packages under mjb44:

/subsystem=logging/file-handler=my-app:add(append=true, autoflush=true, file={relative-to=jboss.server.log.dir, path=myapp.log})
/subsystem=logging/logger=mjb44:add(level=INFO, handlers=[my-app])

Issuing the above commands on the CLI:

$ ./bin/jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
[disconnected /] connect
[standalone@localhost:9999 /] /subsystem=logging/file-handler=my-app:add(append=true, autoflush=true, file={relative-to=jboss.server.log.dir, path=myapp.log})
{"outcome" => "success"}
[standalone@localhost:9999 /] /subsystem=logging/logger=mjb44:add(level=INFO, handlers=[my-app])
{"outcome" => "success"}
[standalone@localhost:9999 /] 
… results in the following standalone.xml: <subsystem xmlns="urn:jboss:domain:logging:1.3"> <console-handler name="CONSOLE"> <level name="INFO"/> <formatter> <pattern-formatter pattern="%K{level}%d{MM-dd HH:mm:ss} %-5p [%c] (%t) %s%E%n"/> </formatter> </console-handler> <file-handler name="my-app" autoflush="true"> <file relative-to="jboss.server.log.dir" path="myapp.log"/> <append value="true"/> </file-handler> <periodic-rotating-file-handler name="FILE" autoflush="true"> <formatter> <pattern-formatter pattern="%d{MM-dd HH:mm:ss} %-5p [%c] (%t) %s%E%n"/> </formatter> <file relative-to="jboss.server.log.dir" path="server.log"/> <suffix value=".yyyy-MM-dd"/> <append value="true"/> </periodic-rotating-file-handler> <logger category="com.arjuna"> <level name="WARN"/> </logger> <logger category="org.apache.tomcat.util.modeler"> <level name="WARN"/> </logger> <logger category="org.jboss.as.config"> <level name="DEBUG"/> </logger> <logger category="sun.rmi"> <level name="WARN"/> </logger> <logger category="jacorb"> <level name="WARN"/> </logger> <logger category="jacorb.config"> <level name="ERROR"/> </logger> <logger category="mjb44"> <level name="INFO"/> <handlers> <handler name="my-app"/> </handlers> </logger> <root-logger> <level name="INFO"/> <handlers> <handler name="CONSOLE"/> <handler name="FILE"/> </handlers> </root-logger> </subsystem>

… the effect is the following:

This is in many respects the best of both worlds and the only disadvantage is that we can't keep the logging configuration in our application's source control (as there is no log4j.xml file and the configuration was made directly in the server's standalone.xml).

use log4j and provide your own log4j.xml

By including a log4j.xml file in tha classpath (typically in WEB-INF/classes), you can issue Logger#info statements in your application that end up in some application-specific log file (not server.log).

NB: as in the previous approach, there is no reason to provide the Log4j jars in WEB-INF/lib. The JBoss server provides its own Log4j implementation in a module (in fact it is based on a fork of Log4j as they had to tweak something). Theoretically it should be possible to provide your own Log4j jar in WEB-INF/lib and include a jboss-deployment-structure.xml in META-INF to disable the JBoss own Log4j module as described here but I didn't have much luck with this approach.

E.g. I've confirmed that the following log4j.xml sends logger.info output to file cas-auth.log.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %5p %c{2}: %m%n" /> </layout> </appender> <appender name="FILE" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="${jboss.server.log.dir}/cas-auth.log" /> <param name="MaxFileSize" value="1MB" /> <param name="MaxBackupIndex" value="100" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{yyyy-MM-dd hh:mm:ss:sss z}] %c %5p: %m%n" /> </layout> </appender> <root> <priority value="info" /> <appender-ref ref="CONSOLE" /> <appender-ref ref="FILE" /> </root> </log4j:configuration>

However, even though the above logger has a ConsoleAppender attached to it, no logger.info output is seen in either the console or in server.log (maybe a JBoss EAP 6.2.0 bug?)

Also, I have been advised against using a console appender in my own logger in this thread. The gist is:

I'd also advise against using the ConsoleAppender as it could result in deadlocks unless you disable the console-handler on the server.
… and:
With regards to using the ConsoleAppender. The issues is you'd have two different log managers writing to the same output stream. In most cases it should work, it's just not a good practice to have two different objects writing to the same output stream.