I am just stuck and need some pointers. I have followed instruction on creating my own logging implementation, logging factory, and guice module; but just aren't sure what I am missing...
My custom logger implemented w/ Factory. This extends from jClouds BaseLogger; not shown is the actually logging functionality. Also created is the Factory, which I based off of their implementation of Log4JLogger Factory. In this I needed a static getLogger and used the slf4j's LoggerFactory and casted it to jClouds interface type Logger. I added the '@Inject' annotation but I feel like this is what should be on the jClouds side, not mine. (Not sure). What am I missing though??
import org.jclouds.logging.BaseLogger;
import org.jclouds.logging.Logger;
import com.google.inject.Inject;
public class NullLoggerExt extends BaseLogger {
private final org.jclouds.logging.Logger logger;
public static class NullLoggerExtFactory implements LoggerFactory {
public Logger getLogger(String category) {
return new NullLoggerExt( (Logger) org.slf4j.LoggerFactory.getLogger(category) );
}
}
@Inject <--- is this what I need?
public NullLoggerExt(org.jclouds.logging.Logger logger) {
this.logger = logger;
}
.
. (implemented abstract methods)
.
}
My custom logger Module
import NullLoggerExt;
import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.logging.config.LoggingModule;
public class NullLoggerModuleExt extends LoggingModule {
@Override
public LoggerFactory createLoggerFactory() {
return new NullLoggerExt.NullLoggerExtFactory();
}
}
My Guice module
import NullLoggerExt;
import com.google.inject.AbstractModule;
import org.jclouds.logging.Logger;
public class BindLoggerModule extends AbstractModule {
@Override
protected void configure() {
bind(Logger.class).to(NullLoggerExt.class);
}
}
This section will describe where I am using it.
public class CloudHandler
{
//Actual logger
private static final Iterable<Module> detailedTrace =
ImmutableSet.<Module> of( new SLF4JLoggingModule() );
Injector injector = Guice.createInjector(new BindLoggerModule());
NullLoggerModuleExt customLog = injector.getInstance(NullLoggerModuleExt.class);
//My performance logger
private final Iterable<Module> baseLog =
ImmutableSet.<Module> of( customLog );
public int connect( ... ) {
contextBuilder...
//Problem area
if (debug mode == true)
contextBuilder.modules( detailedTrace );
else
contextBuilder.modules( baseLog );
//Throws CreationException
ctx = contextBuilder.buildView( BlobStoreContext.class );
return Success or Failure;
}
}
This approach is wrong, because you are trying to inject a Logger implementation that is bound to that exact same class, so you will get a recursive loop there.
If you are just trying to modify how the SLF4j logging driver works, you could just extend its classes. However, if you are trying to "decorate" any jclouds logger with the null logger, and then delegate to the logging driver when needed, you could go for a more generic approach by using the following logging classes and module:
static class DelegatingNullLogger extends BaseLogger {
private final Logger logger;
public static class DelegatingNullLoggerFactory implements LoggerFactory {
private final LoggerFactory delegate;
public DelegatingNullLoggerFactory(LoggerFactory delegate) {
this.delegate = checkNotNull(delegate, "delegate");
}
@Override
public Logger getLogger(String category) {
return new DelegatingNullLogger(delegate.getLogger(category));
}
}
public DelegatingNullLogger(Logger logger) {
this.logger = logger;
}
// Implement methods
}
static class NullDelegatingLoggingModule extends LoggingModule {
private final LoggerFactory loggerFactory;
public NullDelegatingLoggingModule(LoggerFactory loggerFactory) {
this.loggerFactory = checkNotNull(loggerFactory, "loggerFactory");
}
@Override
public LoggerFactory createLoggerFactory() {
return new DelegatingNullLogger.DelegatingNullLoggerFactory(loggerFactory);
}
}
This code will first create a logger that will delegate to an underlying logger that can be Log4j, SLF4j or whatever when it comes to log messages, and the provided module, configures the delegate logger that will be passed.
You can use this as follows, for example to have the null logger delegate to the SLF4j logging driver:
LoggerFactory loggerFactory = new SLF4JLogger.SLF4JLoggerFactory();
LoggingModule loggingModule = new NullDelegatingLoggingModule(loggerFactory);
BlobStoreContext ctx = ContextBuilder.newBuilder("provider")
.modules(ImmutableSet.of(loggingModule))
(...)
.buildView(BlobStoreContext.class);