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