Redirecting all logging (also from all third party libs) to fabric3 @Monitor

There are at least 3 ways, how this can be achieved:

  1. Use the fabric3-monitor-log in you application by embedding it in META-INF/lib (the Fabric3 contribution plugin can do this). You will then need to exclude commons logging and SLF4J implementations from the transitive dependencies of any libraries you may have. This is because fabric3-monitor-log replaces those implementations with its own that redirects out to the monitor infrastructure. This will require a dependency on the Fabric3 SPI package.
  2. Create your own redirection, potentially using org.fabric3.spi.monitor.MonitorLocator from the SPI. You may need to do this if you have a library that uses custom logging. This will require a dependency on the Fabric3 SPI package.
  3. Create a component in Fabric3 that is injected with a org.fabric3.api.MonitorChannel using the @Monitor annotation. This component can then set a singleton or some other mechanism to redirect from third-party logging to Fabric3. The advantage of this approach is there is no dependency on SPI and you have more control over monitoring - for example, you can set a custom destination or multiple destinations.

I will write about the third approach:
Usualy on projects I'm using common module, which contains definitions and some common classes. We put the logger impl there.
This common module than needs to be imported in every component. In common, we have these dependencies:

<!-- LOGGING -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jul-to-slf4j</artifactId>
            <version>1.6.5</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.6.5</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.6.5</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

We will redirect all logs through slf4j, while we use bridges: jul-to-slf4j, log4j-over-slf4j and jcl-over-slf4j to redirect all logs from log4j, commons logging and java.util.logging.

We need to exclude log4j, commons logging from the dependencies. Ususaly that's lot of work, as these loggers are used widely across the open source libraries.
We do this by adding exclusions to dependencies where needed:

<exclusion>
 <groupId>commons-logging</groupId>
 <artifactId>commons-logging</artifactId>
 </exclusion>
 <exclusion>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 </exclusion>

Than in common module sca-contribution.xml we export packages:

<export.java package="org.apache.commons.logging.*"/>
<export.java package="org.slf4j.*"/>
<export.java package="org.apache.log4j.*"/>

while we import them where ever the common is used:

<import.java package="org.apache.commons.logging.*"/>
<import.java package="org.slf4j.*"/>
<import.java package="org.apache.log4j.*"/>

We need our own implementation of slf4j. I used the one from fabric3-core with small adjustments. We put it to common to org.slf4j.impl package.

It's very simple logger impl., just as an example, configuration can be enhanced a lot. You just call setLogger() on StaticLoggerBinder in @Init method of first loaded component, populating it with fabric3 @Monitor, in our case, the ILogger.
Levels are set staticaly through the getLogger() method in StaticLoggerBinder.

You can find these files in attachment.

ILogger.java 

StaticMDCBinder.java 

StaticLoggerBinder.java

NoOpLogger.java