On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma <remko.po...@gmail.com> wrote:

> Gary,
>
> The hard-coded levels were proposed because it seemed that the extensible
> enum idea raised by Nick was not going to be accepted.
> My original position was that Markers could fulfill the requirement but
> Nick and yourself made it clear that this was not satisfactory.
>
> With extensible enums and markers off the table it seemed that the
> hard-coded levels was the only alternative, and discussion ensued about
> what these levels should be called and what strength they should have.
>
> During this discussion, several people, including me, repeatedly expressed
> strong reservations about adding pre-defined levels, but by this time I
> think people were thinking there was no alternative.
>
> It looked like we were getting stuck, with half the group moving in one
> direction ("add pre-defined levels!") and the other half wanting to move in
> another direction ("don't add pre-defined levels!"). I asked that we
> re-reviewed our assumptions and try to reach a solution that would satisfy
> all users.
>
> We then decided to explore the option of using extensible enums again.
> This is still ongoing, but I haven't seen anyone arguing against this idea
> since we started this thread.
>
> Hard-coded levels and the extensible enum are different solutions to the
> same problem.
>

Hello All:

Absolutely not. See my DEFCON example.
Talking about an "extensible enum" is mixing design and implementation, we
are talking about 'custom' and/or 'extensible' levels.
Custom/Extensible levels can be designed to serve one or all of:

- Allow inserting custom levels between built-in levels.
- Allow for domain specific levels outside of the concept of built-in
levels, the DEFCON example.
- Should the custom levels themselves be extensible?

Gary


> The extensible enum solution satisfies all of us who are opposed to adding
> pre-defined levels, while also satisfying the original requirement raised
> by Nick and yourself. Frankly I don't understand why you would still want
> the pre-defined levels.
>
> Remko
>
>
>
> On Sat, Jan 25, 2014 at 12:53 AM, Gary Gregory <garydgreg...@gmail.com>wrote:
>
>> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma <remko.po...@gmail.com>wrote:
>>
>>> Gary,
>>>
>>> I think that's a very cool idea!
>>> Much more flexible, powerful and elegant than pre-defined levels could
>>> ever be.
>>>
>>
>> As I wrote: "I am discussing custom levels here with the understanding
>> that this is a separate topic from what the built-in levels are."
>>
>> I'm not sure why you want to make the features mutually exclusive. (Some)
>> others agree that these are different features.
>>
>> I see two topics:
>>
>> - What are the default levels for a 21st century logging framework. Do we
>> simply blindly copy Log4j 1? Or do we look at frameworks from different
>> languages and platforms for inspiration?
>> - How (not if, I think we all agree) should we allow for custom levels.
>>
>> Gary
>>
>> It definitely makes sense to design the extensible enum with this
>>> potential usage in mind.
>>>
>>> Remko
>>>
>>>
>>> On Friday, January 24, 2014, Gary Gregory <garydgreg...@gmail.com>
>>> wrote:
>>>
>>>> I am discussing custom levels here with the understanding that this is
>>>> a separate topic from what the built-in levels are. Here is how I convinced
>>>> myself that custom levels are a “good thing”.
>>>>
>>>> No matter which built-in levels exits, I may want custom levels. For
>>>> example, I want my app to use the following levels DEFCON1, DEFCON2,
>>>> DEFCON3, DEFCON4, and DEFCON5. This might be for one part of my app or a
>>>> whole subsystem, no matter, I want to use the built-in levels in addition
>>>> to the DEFCON levels. It is worth mentioning that if I want that feature
>>>> only as a user, I can “skin” levels in a layout and assign any label to the
>>>> built-in levels. If I am also a developer, I want to use DEFCON levels in
>>>> the source code.
>>>>
>>>>
>>>> At first, my code might look like:
>>>>
>>>>
>>>> logger.log(DefconLevels.DEFCON5, “All is quiet”);
>>>>
>>>>
>>>> Let’s put aside for now the type of DefconLevels.DEFCON* objects. I am
>>>> a user, and I care about my call sites.
>>>>
>>>>
>>>> What I really want of course is to write:
>>>>
>>>>
>>>> defconLogger.defcon5(“All is quiet”)
>>>>
>>>>
>>>> Therefore, I argue that for any “serious” use of a custom level, I will
>>>> wrap a Logger in a custom logger class providing call-site friendly methods
>>>> like defcon5(String).
>>>>
>>>>
>>>> So now, as a developer, all I care about is DefConLogger. It might wrap
>>>> (or subclass) the Log4J Logger, who knows. The implementation of
>>>> DefConLogger is not important to the developer (all I care is that the
>>>> class has ‘defconN’ method) but it is important to the configuration
>>>> author. This tells me that as a developer I do not care how DefConLogger is
>>>> implemented, with custom levels, markers, or elves. However, as
>>>> configuration author, I also want to use DEFCON level just like the
>>>> built-in levels.
>>>>
>>>>
>>>> The configuration code could allow hiding the fact that markers (or
>>>> elves) are used so that the configuration looks like a normal
>>>> configuration. Maybe a markerLevel attribute is used, who knows. The point
>>>> is that this is now getting too complicated and too clever. Bottom line:
>>>> real custom levels (not hidden through markers and definitively not elves)
>>>> are needed to cleanly implement the custom level feature.
>>>>
>>>>
>>>> Now, I am convinced that custom levels are needed and useful.
>>>>
>>>>
>>>> Next up is how to implement them, a different story… but still based on
>>>> the fact that I want a DefConLogger class, that’s my user story. First, the
>>>> obvious, it would be nice to have:
>>>>
>>>>
>>>> public enum DefConLevel { DEFCON1, DEFCON2, DEFCON3, DEFCON4, DEFCON5 }
>>>>
>>>>
>>>> The order would determine the precedence from most to least important
>>>> level. The enum might not be strictly needed (at first at least) since I
>>>> 80/20 care about methods on DefConLogger, not how it works internally.
>>>>
>>>>
>>>> So how do I write DefConLogger?
>>>>
>>>>
>>>> Wouldn’t it be nice to be able to write:
>>>>
>>>>
>>>> @CustomLogger(levels=DefConLevel.class)
>>>> public class DefConLogger {}
>>>>
>>>>
>>>> And have Log4J generate the boiler plate code (If you have the right
>>>> magic hooked up in your IDE)? It might generate bytecodes directly, not
>>>> sure. There are all sorts of code BC and generation possibilities with ASM,
>>>> BCEL or a code generator.
>>>>
>>>>
>>>> That still leaves the implementation TDB but then it really does not
>>>> matter how we do it, as long as we do the dirty work for the user.
>>>>
>>>>
>>>> Well, we care about the implementation on this ML of course.
>>>>
>>>>
>>>> Gary
>>>>
>>>>
>>>> On Wed, Jan 22, 2014 at 10:05 PM, Paul Benedict 
>>>> <pbened...@apache.org>wrote:
>>>>
>>>>> As Gary wanted, a new thread....
>>>>>
>>>>> First, each enum needs an inherit strength. This would be part of the
>>>>> interface. Forgive me if the word "strength" is wrong; but it's the 100,
>>>>> 200, 300, etc. number that triggers the log level. So make sure the
>>>>> interface contains the intLevel() method.
>>>>>
>>>>> Second, we need to know the name, right? The name probably requires a
>>>>> new method since it can't be extracted from the enum anymore.
>>>>>
>>>>> public interface Level {
>>>>> int intLevel();
>>>>> String name();
>>>>> }
>>>>>
>>>>> PS: The intStrength() name seems hackish. What about strength() or
>>>>> treshold()?
>>>>>
>>>>> Third, the registration can be done manually by providing a static
>>>>> method (as your did Remko) that the client needs to invoke, or you could
>>>>> have a class-path scanning mechanism. For the latter, you could introduce 
>>>>> a
>>>>> new annotation to be placed on the enum class.
>>>>>
>>>>> @CustomLevels
>>>>> public enum MyCustomEnums {
>>>>> }
>>>>>
>>>>> Paul
>>>>>
>>>>> On Wed, Jan 22, 2014 at 8:52 PM, Remko Popma <remko.po...@gmail.com>wrote:
>>>>>
>>>>>> Paul, can you give a bit more detail?
>>>>>>
>>>>>> I tried this: copy the current Level enum to a new enum called
>>>>>> "Levels" in the same package (other name would be fine too). Then
>>>>>> change Level to an interface (removing the constants and static methods,
>>>>>> keeping only the non-static methods). Finally make the Levels enum
>>>>>> implement the Level interface.
>>>>>>
>>>>>> After this, we need to do a find+replace for the references to
>>>>>> Level.CONSTANT to Levels.CONSTANT and Level.staticMethod() to
>>>>>> Levels.staticMethod().
>>>>>>
>>>>>> Finally, the interesting part: how do users add or register their
>>>>>> custom levels and how do we enable the Levels.staticLookupMethod(String,
>>>>>> Level) to recognize these custom levels?
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Thursday, January 23, 2014, Paul Benedict <pbened...@apache.org>
>>>>>> wrote:
>>>>>>
>>>>>>> Agreed. This is not an engineering per se, but really more about if
>>>>>>> the feature set makes sense.
>>>>>>>
>>>>>>> Well if you guys ever look into the interface idea, you'll give
>>>>>>> log4j the feature of getting enums to represent custom levels. That's
>>>>>>> pretty cool, IMO. I don't know if any other logging framework has that 
>>>>>>> and
>>>>>>> that would probably get some positive attention. It shouldn't be so 
>>>>>>> hard to
>>>>>>> do a find+replace on the code that accepts Level and replace it with
>>>>>>> another name. Yes, there will be some minor refactoring that goes with 
>>>>>>> it,
>>>>>>> but hard? It shouldn't be.
>>>>>>>
>>>>>>> A name I propose for the interface is LevelDefinition.
>>>>>>>
>>>>>>> Paul
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Jan 22, 2014 at 6:48 PM, Gary Gregory <
>>>>>>> garydgreg...@gmail.com> wrote:
>>>>>>>
>>>>>>> Hi, I do not see this as an engineering problem but more a feature
>>>>>>> set definition issue. So while there may be lots of more or less 
>>>>>>> internally
>>>>>>> complicated ways of solving this with interfaces, makers and whatnots, 
>>>>>>> the
>>>>>>> built in levels are the most user friendly.
>>>>>>>
>>>>>>> I have have lots of buttons, knobs and settings on my sound system
>>>>>>> that I do not use, just like I do not use all the methods in all the
>>>>>>> classes in the JRE...
>>>>>>>
>>>>>>> Gary
>>>>>>>
>>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> E-Mail: garydgreg...@gmail.com | ggreg...@apache.org
>>>> Java Persistence with Hibernate, Second 
>>>> Edition<http://www.manning.com/bauer3/>
>>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
>>>> Spring Batch in Action <http://www.manning.com/templier/>
>>>> Blog: http://garygregory.wordpress.com
>>>> Home: http://garygregory.com/
>>>> Tweet! http://twitter.com/GaryGregory
>>>>
>>>
>>
>>
>> --
>> E-Mail: garydgreg...@gmail.com | ggreg...@apache.org
>> Java Persistence with Hibernate, Second 
>> Edition<http://www.manning.com/bauer3/>
>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
>> Spring Batch in Action <http://www.manning.com/templier/>
>> Blog: http://garygregory.wordpress.com
>> Home: http://garygregory.com/
>> Tweet! http://twitter.com/GaryGregory
>>
>
>


-- 
E-Mail: garydgreg...@gmail.com | ggreg...@apache.org
Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
Spring Batch in Action <http://www.manning.com/templier/>
Blog: http://garygregory.wordpress.com
Home: http://garygregory.com/
Tweet! http://twitter.com/GaryGregory

Reply via email to