I have an EAR deployed on Jboss 4.2.3 with the following jboss-app.xml configuration file :
<jboss-app>
<loader-repository>
com.al6:loader=MyProject.ear
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</loader-repository>
</jboss-app>
And an application.xml file :
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/application_1_4.xsd"
version="1.4">
<description>Manages project business layer</description>
<display-name>MyProject</display-name>
<module>
<ejb>MyProject.jar</ejb>
</module>
</application>
And in my Jboss log file :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!-- ===================================================================== -->
<!-- -->
<!-- Log4j Configuration -->
<!-- -->
<!-- ===================================================================== -->
<!-- $Id: jboss-log4j.xml 75507 2008-07-08 20:15:07Z stan.silvert@jboss.com $ -->
<!--
| For more configuration infromation and examples see the Jakarta Log4j
| owebsite: http://jakarta.apache.org/log4j
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<!-- ================================= -->
<!-- Preserve messages in a local file -->
<!-- ================================= -->
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="${jboss.server.log.dir}/server.log"/>
<param name="Append" value="false"/>
<param name="Threshold" value="INFO"/>
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
</layout>
</appender>
<!-- ============================== -->
<!-- Append messages to the console -->
<!-- ============================== -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
<!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="INFO" />
<appender-ref ref="FILE"/>
</root>
</log4j:configuration>
Until now, all the logging output was using "System....println", which is not a good practice at all.
So, I tried to change to logger.info with :
protected org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(getClass());
But, after that, I'm not gonna had any log at all, nothing.
I tried to add a category in the jboss log configuration file, like :
<category name="com.myproject">
<priority value="INFO" />
<appender-ref ref="FILE"/>
</category>
But nothing change.
So I used my own log4j implementation observing a log4j.properties file which I can modify without redeploy :
package com.myproject;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class Log4jConfigurator implements Runnable {
private static final Logger logger = Logger.getLogger(Log4jConfigurator.class);
private final Path log4jConfigPath;
public Log4jConfigurator(String log4jConfigFile) {
this.log4jConfigPath = Paths.get(log4jConfigFile).toAbsolutePath();
}
@Override
public void run() {
try {
WatchService watcher = log4jConfigPath.getParent().getFileSystem().newWatchService();
log4jConfigPath.getParent().register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
while (!Thread.currentThread().isInterrupted()) {
WatchKey key = watcher.take();
for (WatchEvent<?> event : key.pollEvents()) {
if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY &&
log4jConfigPath.getFileName().toString().equals(event.context().toString())) {
logger.info("Reloading log4j configuration from file: " + log4jConfigPath);
PropertyConfigurator.configure(log4jConfigPath.toString());
}
}
key.reset();
}
} catch (InterruptedException e) {
logger.info("Log4j configuration monitoring thread interrupted.");
} catch (Exception e) {
logger.error("Error while monitoring log4j configuration file", e);
}
}
}
It works perfectly !
BUT, two problems :
1- I used the same file that Jboss used (server.log), it seems to work but is this ok to write log from jboss and my own log4j in the same file ?
2- All the log from this are messed up by log4j I presume, and so I had twice informations :
2023-01-25 17:24:44,493 INFO [STDOUT] [ INFO] com.myproject.someBusiness:938 - getOrder
2023-01-25 17:24:44,546 INFO [STDOUT] [ INFO] com.myproject.someBusiness:3138 - prices are refreshed
I already delete the date in log4j xml configuration file to not having twice the log date. But for the rest (INFO...), it's all contained in the %m variable, so I can't do anything.
Why jboss add it's own prefix ?
Seems to work with this solution :
I put my log4j.properties into /opt/jboss/server/myserverinstance/conf/ directory.
I ask to Jboss to check this log4j.properties file instead of the old jboss-log4j.xml. In jboss-service.xml :
<!-- ==================================================================== -->
<!-- Log4j Initialization -->
<!-- ==================================================================== -->
<mbean code="org.jboss.logging.Log4jService"
name="jboss.system:type=Log4jService,service=Logging"
xmbean-dd="resource:xmdesc/Log4jService-xmbean.xml">
<attribute name="ConfigurationURL">resource:log4j.properties</attribute>
<attribute name="Log4jQuietMode">true</attribute>
<attribute name="RefreshPeriod">10</attribute>
</mbean>
Then, I let my app check also this same properties file, no change made here.
I put this in my log4.properties file :
#Define root logger options
log4j.rootLogger=INFO, server
log4j.appender.status=org.apache.log4j.DailyRollingFileAppender
log4j.appender.status.File=${jboss.server.log.dir}/status.log
log4j.appender.status.DatePattern='.'yyyy-MM-dd
log4j.appender.status.layout=org.apache.log4j.PatternLayout
log4j.appender.status.layout.ConversionPattern=%d %-5p [%c] %m%n
log4j.appender.server=org.apache.log4j.DailyRollingFileAppender
log4j.appender.server.File=${jboss.server.log.dir}/server.log
log4j.appender.server.DatePattern='.'yyyy-MM-dd
log4j.appender.server.layout=org.apache.log4j.PatternLayout
log4j.appender.server.layout.ConversionPattern=%d %-5p [%c] %m%n
And that's it, it works great,I have both server messages and my app messages, without weird duplicate date, log level or anything.