I would like to propose not doing anything on this subject until there is a request from the community. It's probably way too easy to over-engineer and devise solutions to problems that a small percentage (or zero?) of the users will need. I am all for ingenuity and passion, but after GA occurs and there's no experience with custom levels directly, we might get a better idea what the "right" answer is.
So slate this for 2.x in JIRA and let's get to GA. On Wed, Jan 29, 2014 at 4:53 PM, Matt Sicker <boa...@gmail.com> wrote: > Annotation processing is beyond over-engineered, yet it still lacks some > of the neat features from runtime annotation "processing". I've been > meaning to look more into it as it might be useful for injecting Loggers > using annotations. > > > On 29 January 2014 07:46, Remko Popma <remko.po...@gmail.com> wrote: > >> >> >> On Wednesday, January 29, 2014, Nick Williams < >> nicho...@nicholaswilliams.net> wrote: >> >>> >>> On Jan 28, 2014, at 5:43 PM, Remko Popma wrote: >>> >>> I would really like everyone's feedback on this. I have two questions: >>> >>> 1. Does this fulfill everyone's requirements? >>> Another way of asking this is: would you use this in your own projects? >>> (If not, why not?) >>> >>> >>> Personally, no. I don't like the code generation for IDE integration >>> issues. I'd prefer an interface I wrote. >>> >> >> I'm not sure what you mean by IDE integration issues, but let's not lose >> sight of why we are doing this in the first place: we want to provide >> convenience methods to make custom levels as easy to use as built-in >> levels. >> I'm beginning to feel that we are adding additional requirements on top >> of this that make it difficult to achieve our original goal... >> >> >>> 2. What do you think of this approach? >>> Obviously code generation has drawbacks. For one thing, IDE refactoring >>> tools don't work and API changes don't cause compile errors in the >>> generator itself, only in the generated code. (I plan to add a JUnit test >>> that generates a custom logger, compiles it and executes the custom logging >>> methods so we can at least catch issues during the build.) >>> The advantage is that it is open-ended and can deal with any custom >>> level users can dream up. >>> >>> Is this trade-off acceptable? >>> Are there other ways to solve this? >>> >>> >>> Also IMO, I would tend to steer away from only generating a concrete >>> class. The interface and implementation should be separate. Imagine a Log4j >>> fixing a bug in the generation code and releasing 2.0.1 or whatever. Now >>> the user has a generated implementation, so they can't /just/ upgrade their >>> Maven dependency. They /also/ have to re-generate their code. That's a >>> pain. However, with the interface and implementation separate, the >>> interface probably doesn't have to change, and the implementation will >>> change as soon as they fire up their app with the latest Log4j. >>> >>> Also, if you separate the interface and implementation, you can make the >>> generation of the interface optional. The user can /choose/ whether to >>> generate the interface or create the interface themselves. Then the >>> implementation generates at runtime. >>> >> >> My original intuition was also to start with a separate interface and >> implementation but as I was thinking about "what is the simplest thing that >> could possibly work?" I ended up with this design. Please don't dismiss >> this solution just because it is based on a concrete class. >> >> Generating an implementation at runtime just seems so much more complex. >> It involves inspecting the signature of every method on the interface to >> see which Logger.log(Level, ...) method it should be mapped to. And what is >> there is no match? We would need to throw an IllegalArgumentException at >> runtime. This problem does not exist with the concrete class. >> >> I've taken a look at ASM (http://asm.ow2.org/) to generate byte >> code on-the-fly but I have kind of given up on that idea. (If anyone else >> wants to take this on please feel free but it seems the result may >> be fragile and difficult to maintain.) >> >> The alternative is probably annotation processing. This is interesting >> stuff and I look forward to taking a closer look into this in the next week >> or so. But just looking at the API, "simple" is not the word that comes to >> mind. :-) >> Also be aware that generating an implementation class at runtime would >> require users to have tools.jar in the classpath so we can compile the >> generated implementation class source code at runtime. The concrete class >> does not need additional jars. >> >> So there's a bunch of trade-offs here. I'd like to understand annotation >> processing a bit better first, but I still think the simplicity of the >> concrete class has a lot of appeal. >> >> >> >>> Nick >>> >>> >>> Remko >>> >>> On Tuesday, January 28, 2014, Remko Popma <remko.po...@gmail.com> wrote: >>> >>> I created https://issues.apache.org/jira/browse/LOG4J2-519 for this. >>> Feedback welcome. >>> >>> On Tuesday, January 28, 2014, Remko Popma <remko.po...@gmail.com> wrote: >>> >>> I've started to work on implementing a source code generator along the >>> lines described below. >>> >>> Does anyone disagree with this approach? >>> >>> I was thinking to name the tools Generate$ExtendedLogger and >>> Generate$CustomLogger and put the Generate class in the log4j-api project >>> under org.apache.logging.log4j.util or create a new package called >>> org.apache.logging.log4j.experimental. >>> >>> Thoughts? >>> >>> On Tuesday, January 28, 2014, Remko Popma <remko.po...@gmail.com> wrote: >>> >>> More thoughts on CustomLogger/ExtendedLogger source code generation: >>> >>> Perhaps I was overcomplicating things... >>> Why don't we generate source for a concrete class instead of an >>> interface+implementation? >>> >>> If users want to /extend/ Logger, this class would extend >>> AbstractLoggerWrapper (which has the standard debug(), info(), warn(), ... >>> methods). >>> >>> If users want to hide the standard methods, the generated class would >>> simply not extend AbstractLoggerWrapper, so the only public methods would >>> be the generated methods for the custom log levels. >>> >>> This allows users to generate both extended loggers (with extra methods) >>> and custom domain specific Loggers (like a logger that only has defcon1(), >>> defcon2(), defcon3() methods). >>> >>> > > > -- > Matt Sicker <boa...@gmail.com> > -- Cheers, Paul