Search code examples
jbosslog4jear

Log4j and EAR conflicts with jboss


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 ?


Solution

  • 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.