Logger Plug-ins

Installing a custom logger using the Ice plug-in facility has several advantages. Because the logger plug-in is specified by a configuration property and loaded dynamically by the Ice run time, an application requires no code changes in order to utilize a custom logger implementation. Furthermore, a logger plug-in takes precedence over the per-process logger and the logger supplied in the InitializationData argument during communicator initialization, meaning you can use a logger plug-in to override the logger that an application installs by default.

On this page:

Installing a C++ Logger Plug-in

To install a logger plug-in in C++, you must first define a subclass of Ice::Logger:

C++
class MyLoggerI : public Ice::Logger {
public:

    virtual void print(const std::string& message);
    virtual void trace(const std::string& category, const std::string& message);
    virtual void warning(const std::string& message);
    virtual void error(const std::string& message);
    virtual std::string getPrefix();
    virtual LoggerPtr void cloneWithPrefix(const string& prefix);

    // ...
};

Next, supply a factory function that installs your custom logger by returning an instance of Ice::LoggerPlugin:

C++
extern "C"
{

ICE_DECLSPEC_EXPORT Ice::Plugin*
createLogger(const Ice::CommunicatorPtr& communicator,
             const std::string& name,
             const Ice::StringSeq& args)
{
    Ice::LoggerPtr logger = new MyLoggerI;
    return new Ice::LoggerPlugin(communicator, logger);
}

}

The factory function can have any name you wish; we used createLogger in this example. Refer to the plug-in API for more information on plug-in factories.

The definition of LoggerPlugin is shown below:

C++
namespace Ice {
class LoggerPlugin {
public:
    LoggerPlugin(const CommunicatorPtr&, const LoggerPtr&);

    virtual void initialize();
    virtual void destroy();
};
}

The constructor installs your logger into the given communicator. The initialize and destroy methods are empty, but you can subclass LoggerPlugin and override these methods if necessary.

Finally, define a configuration property that loads your plug-in into an application:

Ice.Plugin.MyLogger=mylogger:createLogger

The plug-in's name in this example is MyLogger; again, you can use any name you wish. The value of the property represents the plug-in's entry point, in which mylogger is the abbreviated form of its shared library or DLL, and createLogger is the name of the factory function.

If the configuration file containing this property is shared by programs in multiple implementation languages, you can use an alternate syntax that is loaded only by the Ice for C++ run time:

Ice.Plugin.MyLogger.cpp=mylogger:createLogger

Installing a Java Logger Plug-in

To install a logger plug-in in Java, you must first define a subclass of Ice.Logger:

Java
public class MyLoggerI implements Ice.Logger {

    public void print(String message) { ... }
    public void trace(String category, String message) { ... }
    public void warning(String message) { ... }
    public void error(String message) { ... }
    public String getPrefix() { ... }
    public Logger cloneWithPrefix(String prefix) { ... }

    // ...
}

Next, define a factory class that installs your custom logger by returning an instance of Ice.LoggerPlugin:

Java
public class MyLoggerPluginFactoryI implements Ice.PluginFactory {
    public Ice.Plugin create(Ice.Communicator communicator,
                             String name, String[] args)
    {
        Ice.Logger logger = new MyLoggerI();
        return new Ice.LoggerPlugin(communicator, logger);
    }
}

The factory class can have any name you wish; in this example, we used MyLoggerPluginFactoryI. Refer to the plug-in API for more information on plug-in factories.

The definition of LoggerPlugin is shown below:

Java
package Ice;

public class LoggerPlugin implements Plugin {
    public LoggerPlugin(Communicator communicator, Logger logger)
    {
        // ...
    }

    public void initialize() { }

    public void destroy() { }
}

The constructor installs your logger into the given communicator. The initialize and destroy methods are empty, but you can subclass LoggerPlugin and override these methods if necessary.

Finally, define a configuration property that loads your plug-in into an application:

Ice.Plugin.MyLogger=MyLoggerPluginFactoryI

The plug-in's name in this example is MyLogger; again, you can use any name you wish. The value of the property is the name of the factory class.

If the configuration file containing this property is shared by programs in multiple implementation languages, you can use an alternate syntax that is loaded only by the Ice for Java run time:

Ice.Plugin.MyLogger.java=MyLoggerPluginFactoryI

Installing a C# Logger Plug-in

To install a logger plug-in in .NET, you must first define a subclass of Ice.Logger:

C#
public class MyLoggerI : Ice.Logger {

    public void print(string message) { ... }
    public void trace(string category, string message) { ... }
    public void warning(string message) { ... }
    public void error(string message) { ... }
    public string getPrefix() { ... }
    public Logger cloneWithPrefix(string prefix) { ... }

    // ...
}

Next, define a factory class that installs your custom logger by returning an instance of Ice.LoggerPlugin:

C#
public class MyLoggerPluginFactoryI : Ice.PluginFactory {
    public Ice.Plugin create(Ice.Communicator communicator,
                             string name, string[] args)
    {
        Ice.Logger logger = new MyLoggerI();
        return new Ice.LoggerPlugin(communicator, logger);
    }
}

The factory class can have any name you wish; in this example, we used MyLoggerPluginFactoryI. Refer to the plug-in API for more information on plug-in factories. Typically the logger implementation and the factory are compiled into a single assembly.

The definition of LoggerPlugin is shown below:

C#
namespace Ice {
public partial class LoggerPlugin : Plugin {
    public LoggerPlugin(Communicator communicator, Logger logger)
    {
        // ...
    }

    public void initialize() { }

    public void destroy() { }
}
}

The constructor installs your logger into the given communicator. The initialize and destroy methods are empty, but you can subclass LoggerPlugin and override these methods if necessary.

Finally, define a configuration property that loads your plug-in into an application:

Ice.Plugin.MyLogger=mylogger.dll:MyLoggerPluginFactoryI

The plug-in's name in this example is MyLogger; again, you can use any name you wish. The value of the property is the entry point for the factory, consisting of an assembly name followed by the name of the factory class.

If the configuration file containing this property is shared by programs in multiple implementation languages, you can use an alternate syntax that is loaded only by the Ice for .NET run time:

Ice.Plugin.MyLogger.clr=mylogger.dll:MyLoggerPluginFactoryI

See Also