All,
As we approach a 0.1 release of DeltaSpike, congratulations to everyone on
the good work so far, I feel it's a good time to begin discussing how we
want to handle logging within DeltaSpike. I certainly don't expect this
discussion to result in code for 0.1, but the earlier we begin this
discussion, then it increases the likelihood of it being ready for 0.2
Having been heavily involved in the logging work for Solder, I know the
pain that can be experienced in not getting it right, and also how long it
can take to get right.
I see that there are several goals that we want for logging in DeltaSpike:
1. Make it simple for both extension writers and end users. If it's too
difficult to implement, use or even get right, then we'll frustrate and
alienate developers.
2. It must perform. We don't want to introduce large overhead to
logging.
3. There should be an option to allow/provide type safe logging. [1]
4. An end user should be able to have DeltaSpike log against whichever
logging library they want to utilize in their application. We can
certainly support a specific framework as a default, but it's important to
allow a developer to have the same control over how DeltaSpike is logged as
their own application.
Thoughts?
Regards
Ken Finnigan
[1] An example of type safe logging, from Solder, is to define an interface
such as:
@MessageLogger
public interface BirdLogger {
@Log
@Message("Spotted %s Hawks")
void logHawksSpotted(int number);
@Log
@Message("Spotted %s Owls")
void logOwlsSpotted(int number);
@Log
@Message("Spotted %s Bald Eagles")
void logBaldEaglesSpotted(int number);
}
and then create properties files for each language that you want to support
for these log messages. For instance, if the interface existed in the
org.deltaspike.logging package, then you would create
org.deltaspike.logging.BirdLogger.i18n_fr.properties containing names
matching the methods on the above interface, and values representing
localized versions of the String within @Message.
Finally, a compile time annotation processor would generate concrete
classes for each interface and localized version. In the above example you
would end up with BirdLogger.class and BirdLogger_fr.class
To use the logger that was generated, you then simply do something like:
@Inject
private BirdLogger logger;
public void generateLogMessage() {
logger.logBaldEaglesSpotted(2);
}