Thanks for trying it out. I hadn't actually built from the root - I've built 
the api and core separately - so I'm glad you were able to fix those problems.

I didn't want to commit code until I had the core of something that actually 
functioned. I struggled for a couple of weeks over how to attack 
XMLConfiguration. I don't like the way Logback does it, I didn't want to bring 
in baggage from a third party framework, JAXB isn't a good fit either. In 
short, I wanted something that can be extended without needing to add "rules" 
to the XML processor. See below for what I came up with.

First, while I looked at Log4j and somewhat at Logback, most of the core code 
is completely new. The exception to this is with the Converters for the 
PatternLayout. I took the EnhancedPatternLayout and modified it.

1. I first created an API that had the features I was looking for. That is in 
log4j2-api. While it supports logging a String or an Object it really uses a 
Message interface which is valuable as it allows users to log self-describing 
objects in a convenient manner.
2. I don't like the way Logback binds to the implementation. I used a technique 
I had used in a previous logging framework and used a file to define the 
implementation class. In theory, the API could be modified to support multiple 
logging implementation simultaneously, although I have no plans to implement 
that.
3. Logback suffers from a serious architectural problem that is rooted in 
Log4j. The configured loggers are mixed with the loggers returned from the 
Logger factory. This makes it impossible to reconfigure atomically. With 
Logback the reset method is called on the context which essentially causes the 
system to be in an undefined state until the new configuration is completed 
(log records that should be logged are lost). To solve this I used a design 
that I again borrowed from my previous framework. The configuration is 
separated and on a reconfiguration the new configuration will be created and 
then all the loggers will be updated to use it. While there will be a period 
where some loggers are using the old configuration and some the new there is 
never a point where loggers aren't configured at all.
4. Similar to Logback I added support for Markers and global filters. In 
addition, filters on Loggers are also supported. Unlike Logback, there is only 
a single Filter interface used for global filters, logger filters and appender 
filters.
5. The XMLConfiguration is extremely simple. All it does is read the XML and 
convert the DOM structure to internal Node elements, which contain the node 
attributes, child node references and placeholders for the real object when it 
is constructed. It uses the XML element name to match to a Plugin, so instead 
of writing:

<appender name="console" class="org.apache.log4j.ConsoleAppender">
  <param name="Target" value="System.out"/>
  <layout class="org.apache.log4j.PatternLayout">
     <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
  </layout>
</appender>

you write:

<appenders>
   <Console name="console" target="SYSTEM_OUT">
     <PatternLayout>%-5p %c{1} - %m%n</PatternLayout>
   </Console>
</appenders>

Note that it also would support
   <Console>
      <name>console</name>
      <target>SYSTEM_OUT</target>
     <PatternLayout>%-5p %c{1} - %m%n</PatternLayout>
   </Console>

if you prefer using elements over attributes.

5. I implemented a "Plugin" concept. All core components use annotations to 
describe their name and type. This is used by the XML configuration to 
determine the element names that are used in the configuration file. 
a) Plugins are used for Logger, Appenders, Filters, etc. The BaseConfiguration 
processes the nodes created by XMLConfiguration and saves the resulting Objects 
as appropriate.
b) PatternLayout uses plugins for the converters. To add a new converter an end 
user just needs to create the class with the correct annotation and add the 
package name to the XML configuration as an attribute.
c) Configuration uses plugins to determine the Configuration implementation to 
use. The XMLConfiguration and DefaultConfiguration will always be present, but 
a weight can be specified to allow the new Configuration to take precedence. 
Again, simply placing the Configuration class (with the appropriate 
annotations) in the classpath will cause it to be used. However, if it is in a 
different package that package will have to be registered to be searched either 
by calling a static method on the PluginManager or via a system property (which 
hasn't been implemented yet).
6. java.util.concurrent is used where appropriate. Accordingly, minimal locking 
takes place. No lock is held while Appenders are called which is a serious bug 
in Log4j 1.x as it causes deadlocks.
7, All internal components use the logger API for status reporting. A specific 
StatusLogger provides the implementation. 
8. Layouts return a byte array. In Logback Ceki recently came up with the idea 
of using encoders to allow binary data streams to be sent and received. While 
the requirement seems valid it seemed awkward to wrap a Layout in an encoder.
9. Obviously, everything leverages Java 5 (and might possibly require Java 6 
since that is the JVM I've been using).

The API is not compatible with log4j 1.x. My intention would be to create a 
compatible API (to the degree possible) in a log4j12-api package.

I've benchmarked this against Logback in both the SimplePerfTest and 
ThreadedPerfTest. Logback is slightly faster, probably due to the separation of 
the configuration from the logger, but the difference is about 1 or 2 
hundredths of a second over a million log records that don't pass the log level 
(i.e. no log records are written). 

Although it is a decent amount of code this is meant to be just a starting 
point.  My hope is that others, like yourself, will look at this and figure out 
how to improve on it. And, of course, there are a bunch of Appenders, Filters, 
and other components that are completely missing. 

Ralph

On May 13, 2010, at 10:17 PM, Curt Arnold wrote:

> log4j2-api/pom.xml has a stray </build> (see patch following).  Also, the 
> master pom in BRANCH_2_0_EXPERIMENTAL/rgoers expects log4j2-docs to be in the 
> same directory, when it is currently located one directory closer to root.  
> After those changes, I was able to run "mvn test"/
> 
> I haven't had a chance to review the rest of the commit, but it seems like a 
> substantial amount of work that was done in isolation.  While things are 
> still fresh, can you walk through the whats in this thing and the decisions 
> that you made.
> 
> 
> Index: log4j12-api/pom.xml
> ===================================================================
> --- log4j12-api/pom.xml       (revision 944109)
> +++ log4j12-api/pom.xml       (working copy)
> @@ -28,7 +28,6 @@
>   <packaging>jar</packaging>
>   <name>Log4J Compatibility API</name>
>   <description>The Log4J Compatibility API</description>
> -</build>
>   <dependencies>
>     <dependency>
>       <groupId>junit</groupId>
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
> For additional commands, e-mail: log4j-dev-h...@logging.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to