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

Reply via email to