[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [xmlblaster] Logging (Factory)

Peter Antman wrote:

now its working:

2002-11-06 17:53:23,715 40078 INFO  [org.xmlBlaster.corba] (XmlBlaster MainThrea
d:xmlBlaster:service=XmlBlasterServer,name=Default) [CorbaDriver-/node/http:80.7
2.2.80:3412] You don't need the naming service, i'll switch to builtin http IOR

That was log4j ;-)

Befor committing I would like to present what I have done, and the you
get to say if its going in or not:

1. I have created a org.xmlBlaster.util.log.LogDevicePluginManager,
  which verry much replicates the stuff in PluginManagerBase.

Verrry good.

2. It has its LogPluginInfo (stolen from PluginInfo - but without logging).

What about keeping our PluginInfo, remove all unnecessary logs and only
keep the single log.warn().

In Global.java you do something like this:

public LogChannel getLog(String key) { I_Logger logger = hash.get(key); if (logger == null) { synchronized (this) { if (logger == null) { if (creatingInstance) return null; // !!!! creatingInstance = true; // call plugin .... // this.logger = plugin.load() creatingInstance = false; } } }

And in PluginInfo you check if log is null:

 if (log!=null) log.warn(bla);

3. A LogDevicePluginManager has the extra method (that differentiate it from PluginManagerBase);

  public I_LogDeviceFactory getFactory(String type, String version)
  throws XmlBlasterException


4. The I_LogDeviceFactory uses the same interface as I_Plugin, but is not an I_Plugin due to the logging problem, it has this method to be used when creatting devices.

public LogableDevice getLogDevice(LogChannel channel);

Not necessary if you use our PluginInfo (see 1.), you can use our
I_Plugin again.

5. I have create one FileLogDeviceFactory and one ConsoleLogDeviceFactory, here is the code for the latter:

  public void init(org.xmlBlaster.util.Global glob, LogPluginInfo pluginInfo) throws XmlBlasterException {

public String getType() {return "console";}
public String getVersion() { return "1.0";}
public LogableDevice getLogDevice(LogChannel channel) {
return new LogDeviceConsole(channel);


6. Here is an example of how you can use this in a propert-file: LoggableDevicePlugin[console][1.0]=org.xmlBlaster.util.log.ConsoleLogDeviceFactory LoggableDevicePlugin[file][1.0]=org.xmlBlaster.util.log.FileLogDeviceFactory,logFile=mylogfile logDevice=console logDevice[cb]=console,file logDevice[corba]=console,file


This would mean:
a) for all channels except cb and corba use console.


b)For cb use console and file with the logfile mylogfile


c) for corba use console and file wuth logfile mylogfile.corba

Sounds reasonable.

7. Global has been changed. The plugin manager for logging is created in the constructor. And initLog has changed. This is the code to handle configuring logging through the plugin stuff:

String key = lc.getChannelKey();
boolean useOld = true;//Used to guarante some logging
// There are situations where the manager is actually not there b
if (logDevicePluginManager != null) {
// Get the plugins for the lc.key, first try with key, then globaly
String[] devices = null;
if (key != null)
devices = getProperty().get("logDevice[" + key + "]", new String[0], ",");
if (devices == null || devices.length == 0)
devices = getProperty().get("logDevice", new String[0], ",");
if (devices != null && devices.length > 0) {
for(int i = 0;i<devices.length;i++) {
try {
I_LogDeviceFactory fac = logDevicePluginManager.getFactory(devices[i],"1.0");
LogableDevice dev = fac.getLogDevice(lc);
System.err.println("Setting dev "+dev+"for " +devices[i]+" of key" + key);
if (dev != null)
}catch(XmlBlasterException ex) {
log.error(ME,"Global: error in getting LogDeviceFactory for " + key);
//If we ever reach here, we have some logging device set up
if (useOld) {
log.info(ME,"Using old logging behaviour");

        ... Here is the old log setup code with will be used if the new
            code fails.

What do you say? Is it usable, acceptable, commitable?

Michele and i just discussed  it.
We are thankful if you donate this to xmlBlaster.org.

Here's the code for a Log4j factory (based on the one published on the list a while ago).

Finally all plays together smoothly :-)



package org.backsource.in.blaster;

import org.xmlBlaster.util.Global;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.log.I_LogDeviceFactory;
import org.xmlBlaster.util.log.LogPluginInfo;
import org.jutils.log.LogableDevice;
import org.jutils.log.LogChannel;

import org.apache.log4j.Logger;
* Log4jDeviceFactory.java
* Created: Wed Nov  6 15:08:39 2002
*  at author <a href="mailto:pra at tim.se";>Peter Antman</a>
*  at version $Revision$

public class Log4jDeviceFactory implements I_LogDeviceFactory {
private static final String LOG_DOMAIN="org.xmlBlaster";
private Global glob;
public Log4jDeviceFactory (){
* Get default logFile, glob is searched first,the plugin info.
public void init(Global glob, LogPluginInfo pluginInfo) throws XmlBlasterException {
this.glob = glob;
public String getType() {return "log4j";}
public String getVersion() {return "1.0";}

public LogableDevice getLogDevice(LogChannel channel) {
String key = channel.getChannelKey();
String domain = LOG_DOMAIN;
if ( key != null) {
domain = domain + "."+key;
} // end of if ()
Logger l = Logger.getLogger(domain);
return new Log4jDevice(l);


class Log4jDevice implements LogableDevice {
Logger log = null;
Log4jDevice(Logger log) {
if ( log == null) {
throw new NullPointerException("Logger is not allowed to be null"); } // end of if ()
this.log = log;
public void log(int level, String source, String str) {
StringBuffer logTxt = new StringBuffer();
logTxt.append("[").append(source).append("] ").append(str);
switch (level) {
case LogChannel.LOG_CALL:
case LogChannel.LOG_DUMP:
case LogChannel.LOG_TIME:
case LogChannel.LOG_TRACE:
if (log.isDebugEnabled())
case LogChannel.LOG_ERROR:
case LogChannel.LOG_INFO:
case LogChannel.LOG_WARN:
}; // end of switch
} // end of log
}// Log4jDeviceFactory

Set up with LoggableDevicePlugin[log4j][1.0]=org.backsource.in.blaster.Log4jDeviceFactory logDevice=log4j

In property file and almost all logging (except the one in Global) will
go through log4j instead.


On 6 Nov, Marcel Ruff wrote:

Peter Antman wrote:

Seems as if its verry hard to do this because of circular dependancies:

To set up a logg plugin manager to initialize logging entails creating
one in a Global constructor (so that it is available in initLog).
However the PluginManagerBase uses the Global to set up loging - and
that will mean that PluginManager will start trying to use Global before
it has actually been created:


Any ideas about this, or should I just give up ;-(

Just throw out all logging from PluginManagerBase
but i have just noticed that we use our Classloader there which
probably logs as well  ....

Ok, to not waste too much time on it:

1. Do your own instanciation  and forget the PluginManagerBase
2. Allow some first old style logging before you switch to your
  plugin logging



On  5 Nov, Marcel Ruff wrote:

;-) Ok. I will do a test, and check with you later. One last question:

in the currect impl each LogChannel gets its own LogDevice in initLog,
and the LogDevice gets info from the log channel for its fomatting and
such (I guess). Is this a requirement, because it will not work with the
ideas given above, becuse each type will only be instantiated once.

I believe that doesn't matter, we don't need any formatting when
send to another logging framework.
But i haven't check the code (it's from Juergen Birkle).

Instead the plugins would bhave to be a factories which creates devices
(which could really be done by a generic factory ;-):


Its not pretty.

I think its beautiful, but just follow the way you like best.