2

I want that all logging from HornetQ, which runs embedded in my application, is delegated to slf4j. Unfortunately any attempt failed. I allready tried

  • added jul-to-slf4j
  • installed the bridge SLF4JBridgeHandler.install();
  • Tried the Log4jLogDelegateFactory ("hornetq-configuration.xml" via <log-delegate-factory-class-name>org.hornetq.integration.logging.Log4jLogDelegateFactory</log-delegate-factory-class-name>)
  • Wrote my own LogDelegate and LogDelegateFactory

But whatever I do, the folloing lines are not catched:

13.07.2011 17:42:11 org.hornetq.core.logging.impl.JULLogDelegate warn
WARNUNG: AIO wasn't located on this platform, it will fall back to using pure Java NIO. If your platform is Linux, install LibAIO to enable the AIO journal
13.07.2011 17:42:11 org.hornetq.core.logging.impl.JULLogDelegate info
INFO: Using NIO Journal
13.07.2011 17:42:11 org.hornetq.core.logging.impl.JULLogDelegate info
INFO: Started Netty Acceptor version 3.1.5.GA-r1772

Anything I did miss?

MaDa
  • 10,511
  • 9
  • 46
  • 84
Dag
  • 10,079
  • 8
  • 51
  • 74
  • 1
    The solution with jul-to-slf4j http://stackoverflow.com/questions/9117030/jul-to-slf4j-bridge worked for me with hornetq. – Hugo Duncan Jul 24 '12 at 19:48

3 Answers3

5

I found a complete solution that I want to share with you. I have previously tried each of these on their own, but you have to combine some of the techniques mentioned in other answers.

  • You need to write your own LogDelegate:
import org.hornetq.spi.core.logging.LogDelegate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4jLogDelegate implements LogDelegate {
    private final Logger logger;
    public Slf4jLogDelegate(Class clazz) {
        logger = LoggerFactory.getLogger(clazz);
    }
    @Override
    public void debug(Object message) {
        logger.debug(message.toString());
    }
    @Override
    public void debug(Object message, Throwable t) {
        logger.debug(message.toString(), t);
    }
    @Override
    public void error(Object message) {
        logger.error(message.toString());
    }
    @Override
    public void error(Object message, Throwable t) {
        logger.error(message.toString(), t);
    }
    @Override
    public void fatal(Object message) {
        logger.error(message.toString());
    }
    @Override
    public void fatal(Object message, Throwable t) {
        logger.error(message.toString(), t);
    }
    @Override
    public void info(Object message) {
        logger.info(message.toString());
    }
    @Override
    public void info(Object message, Throwable t) {
        logger.info(message.toString(), t);
    }
    @Override
    public boolean isDebugEnabled() {
        return logger.isDebugEnabled();
    }
    @Override
    public boolean isInfoEnabled() {
        return logger.isInfoEnabled();
    }
    @Override
    public boolean isTraceEnabled() {
        return logger.isTraceEnabled();
    }
    @Override
    public void trace(Object message) {
        logger.trace(message.toString());
    }
    @Override
    public void trace(Object message, Throwable t) {
        logger.trace(message.toString(), t);
    }
    @Override
    public void warn(Object message) {
        logger.warn(message.toString());
    }
    @Override
    public void warn(Object message, Throwable t) {
        logger.warn(message.toString(), t);
    }
}
  • Then you need to write the factory:
import org.hornetq.spi.core.logging.LogDelegate;
import org.hornetq.spi.core.logging.LogDelegateFactory;
public class Slf4jLogDelegateFactory implements LogDelegateFactory {
    // Maybe caching of delegates makes sense?
    @Override
    public LogDelegate createDelegate(Class clazz) {
        return new Slf4jLogDelegate(clazz);
    }
}
  • Then add to your hornetq-configuration.xml the following line: <log-delegate-factory-class-name>yourpackage.Slf4jLogDelegateFactory</log-delegate-factory-class-name>
  • Finally, add the following line before you start the embedded server: org.hornetq.core.logging.Logger.setDelegateFactory(new Slf4jLogDelegateFactory());

I'm just wondering why they can't use proven logging mechanisms, that make it easy to exchange a logger.

staticbeast
  • 2,073
  • 2
  • 22
  • 24
Dag
  • 10,079
  • 8
  • 51
  • 74
  • there are so many logging mechanisms out there. If we tight to any... there's always someone else complaining about it. We also need zero dependencies on HornetQ. That means.. JUL.... If you want a different logger.. you can plug it – Clebert Suconic Jul 14 '11 at 17:32
  • You're absolutly right, when zero dependency is your goal, you have to go with JUL. As a developer I'm just trying to get the logging right, so slf4j is my solution, covering log4j, apache commons logging, avsl, backlog and JUL. But JUL seems to require additional programming efforts because it's tight java integration and can cause (minor) performance drawbacks (SLF4JBridgeHandler). – Dag Jul 14 '11 at 21:07
3

Since you are running Embedded, try adding this code before you start the server:

org.hornetq.core.logging.Logger.setDelegateFactory(new YourOwnDelegateFactory())

You had probably a few messages using the old delegate until the server got it from the config.

Clebert Suconic
  • 5,353
  • 2
  • 22
  • 35
  • Hi Clebert, thanks for your anwser, I tried that too (did forget to mention this before, sorry). The problem was, that still some logs are going to the old logger anyway. I found a solutions that finally covers all log messages, see below. – Dag Jul 14 '11 at 07:00
0

When trying this, I also found that when HornetQServerImpl initialized its static log, it does so before loading the new LogDelegateFactory so instead of using the one I'm specifying on the hornetq-configuration.xml it uses JULLogDelegateFactory so its logs are directly output to the console.

Diving on HornetQ's code I found that it initializes this on Logger.initialise() and that also there it looks for a System property named "org.hornetq.logger-delegate-factory-class-name" to set the default factory, so I used that to fix my problem.

I've fixed this using Spring:

<!-- This property must be set so HornetQServerImpl logger uses our factory -->
<bean id="systemPrereqs" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetClass" value="java.lang.System" />
    <property name="targetMethod" value="setProperty" />
    <property name="arguments">
        <list>
            <value>org.hornetq.logger-delegate-factory-class-name</value>
            <value>my.Slf4jLogDelegateFactory</value>
        </list>
    </property>
</bean>
Alfergon
  • 5,463
  • 6
  • 36
  • 56