Gary,

I think that's a very cool idea!
Much more flexible, powerful and elegant than pre-defined levels could ever
be.
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<javascript:_e({}, 'cvml', '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<javascript:_e({}, 'cvml', '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<javascript:_e({}, 'cvml', '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 <javascript:_e({}, 'cvml',
> 'garydgreg...@gmail.com');> | ggreg...@apache.org <javascript:_e({},
> 'cvml', '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