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

Reply via email to