Log4net was branched from a pre-alpha log4j 1.2, however log4net is not
designed to be an identical implementation to log4j. We have not tracked all
the changes made by log4j since the branch. We have made design decisions in
log4net that are different to some of those in log4j. Now that log4net is at
Apache it may be appropriate to discuss some of the differences between the
frameworks.


> An example:  In the PatternParser class in log4j there are no 
> private instance fields (all fields are either marked as 
> protected, or unmarked giving them default package access.)  
> In the same PatternParser class in log4net all these fields 
> are marked as private.

The PatternParser class has since been redesigned to allow converters to be
bound to variable length patterns, e.g. %thread, %logger, %ndc, %property
etc...

The same change has been made independently in the log4j CVS repository.


> Is there any reason why the log4net authors did this?  Does this 
> "redesign" of the log4j architecture show up anywhere else in 
> the log4net codebase?  If so, are the authors interested in fixing this?

Other differences include (but not limited to):


Log4net exposes an interface (ILog) to clients through the
LogManager.GetLogger call rather than the Logger implementation instance.
This allows the logger implementation to be changed without impacting
clients. The contract is guaranteed by the interface.

Log4net does not return the Logger implementation instance from
LogManager.GetLogger() but rather a wrapper object. This is a handle body
pattern. The body is the Logger implementation. The Logger (ILogger
interface) knows how to log any LoggingEvent object. The handle is passed to
the client and provides a strongly typed API for the client to call, for
example the ILog interface is implemented by the default handle, this
translates calls to Error(message) into a call on the logger. This design
allows different client contracts to be created and used concurrently even
over the same logger. There are some samples of this in the extensions
folder in the log4net download.

The IRepositorySelector interface is quite different in log4net. It is more
complex. Typically components will organise their loggers with
hierarchically distinct names, however this is not enforced. Because .net
has the concept of an assembly log4net can be configured to create a logger
repository for each assembly. This allows the assemblies to have a separate
scope for there loggers which is enforced rather than being by convention.

Log4net uses attributes defined on the assembly which is logging to control
the configuration of the repository selection for that assembly and the
configuration of that repository.

In both log4j and log4net Levels are mappings between a string name and an
integer. The relative position of the levels is defined by the integer
value. In log4j Levels are global. In log4net Levels are specific to a
Repository. This allows different repositories in memory to define different
mappings for levels. While slightly esoteric behaviour this is useful when
composing logging from different sources.

In log4j the DOMConfigurator has intrinsic knowledge of the Hierarchy object
it is configuring. The Hierarchy class is just one possible implementation
of the LoggerRepository interface. In log4net the DOMConfigurator delegates
the parsing of the XML to the LoggerRepository implementation if it supports
the IDOMRepositoryConfigurator interface. This allows different
implementations of the ILoggerRepository to support different XML config
syntax. In log4net the DOMConfigurator just deals with obtaining the XML DOM
from file, stream, .net config section etc... It also can monitor the source
for changes.

In log4net the config file cannot specify the type of ILoggerRepository to
create. Creating the ILoggerRepository of the required type is the
responsibility of the RepositorySelector.

The log4net configuration parser is able to construct and configure
arbitrary objects. The log4j configurator was not able to do this but now is
able to do this via the bean api. However these implementations have evolved
separately. Log4j is getting a completely new XML configurator called joran.

The log4net layout objects (ILayout interface) support formatting to a
TextWriter rather than returning a string. This reduces the number of
temporary objects created while rendering the message.

Log4net supports a different layout interface IRawLayout that renders the
LoggingEvent to an object rather than a string. This is used to render the
LoggingEvent to native objects. The database appender uses this to
optionally render native objects that ADO.NET can consume as parameters to a
prepared statement.

The log4net IObjectRenderer renders the object passed to a TextWriter for
the same reasons as the ILayout. The IObjectRenderer.RenderObject is passed
the RendererMap. This allows a renderer to render nested objects using the
appropriate renderer. For example an array renderer can render each element
in the array using the object renderer from the RendererMap. In log4j the
renderer cannot find the RendererMap for the repository.

The log4net LoggingEvent provides fine grain control over the volatile
content that is fixed. Fixing is required before the LoggingEvent can be
used outside of its appending thread context.


The above is not meant to be a list of the ways in which log4net is better
than log4j, however it is the list of enhancements that I can remember. Of
course, to this list of differences you need to add all the cool features
added to log4j since the branch in June 2001, most of which I don't know
about.



Nicko
------------
Nicko Cadell
log4net dev 

Reply via email to