logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ralph Goers <ralph.go...@dslextreme.com>
Subject Re: Enums and Custom Levels - completed.
Date Mon, 27 Jan 2014 00:10:59 GMT
My first implementation used a real enum that implemented a Level interface.  I have to agree
with Nick that what is currently committed is simpler.

Ralph

On Jan 26, 2014, at 4:00 PM, Matt Sicker <boards@gmail.com> wrote:

> Don't annotation processing plugins work well in IDEs? Either way, there's a maven plugin
already available for doing that, and javac has some sort of support for it already.
> 
> Also, I'm still advocating for using a real enum for Level while providing a Level interface
for all the relevant methods.
> 
> And can't getCustomLogger also provide a default method that uses the getClassName method?
> 
> 
> On 26 January 2014 17:51, Nick Williams <nicholas@nicholaswilliams.net> wrote:
> Generating a logger /interface/ is going to be hard. Sure, writing the code automatically
will be a piece of cake. But then what do we do with that code? The user needs to program
against it. So we have to have a command-line utility or Maven/Ant plug-in to generate the
source pre-compile. However, since the vast majority of users are using IDEs, those IDEs will
still warn them about the interface not existing until they have run the utility to generate
the source.
> 
> I think a better approach would be to allow the user to define an interface that /must/
extend Logger. That interface may contain any methods that match the following signatures
(the interface must have at least one method and there is no limit to the number of methods
it may have):
> 
> void(Marker, Message)
> void(Marker, Message, Throwable t)
> void(Marker, Object)
> void(Marker, Object, Throwable t)
> void(Marker, String)
> void(Marker, String, Object...)
> void(Marker, String throwable)
> void(Message)
> void(Message, Throwable t)
> void(Object)
> void(Object, Throwable t)
> void(String)
> void(String, Object...)
> void(String throwable)
> 
> Each method /must/ be annotated with @LoggingLevel(name = "levelName"). Now LogManager
has a few new methods:
> 
> <T extends Logger> T getCustomLogger(Class<T> loggerClass)
> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Class<?>)
> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Class<?>,
MessageFactory)
> <T extends Logger> T getCustomLogger(Class<T> loggerClass, MessageFactory)
> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Object)
> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Object, MessageFactory)
> <T extends Logger> T getCustomLogger(Class<T> loggerClass, String)
> <T extends Logger> T getCustomLogger(Class<T> loggerClass, String, MessageFactory)
> 
> The user can then obtain such a logger like so, etc.:
> 
> MyLogger logger = LogManager.getCustomLogger(MyLogger.class);
> 
> Log4j will generate an implementation of MyLogger that extends the default implementation,
cache that implementation so that it doesn't have to be implemented again, and then instantiate/cache
the logger instance like normal.
> 
> Make sense?
> 
> N
> 
> On Jan 26, 2014, at 5:32 PM, Scott Deboy wrote:
> 
>> Yes that's what I was thinking.
>> 
>> Scott
>> 
>> On Jan 26, 2014 3:18 PM, "Remko Popma" <remko.popma@gmail.com> wrote:
>> Scott,
>> The way I interpreted Gary's idea was that based on user-specified custom levels,
we would generate an extension of the Logger interface that has a method for each of the custom
levels (well, actually 14 methods for each level :-) ).
>> I haven't really thought about how users would specify their custom levels, as long
as the tool can know what methods to generate. 
>> 
>> We could go one step further and generate the Level subclass from configuration as
well. I suppose that would entail adding a new <Levels> element, with sub-elements like
<Level name="DETAIL" intLevel="450" />... Is that what you are thinking of?
>> 
>> I would be fine with that too, but would like to first focus on generating the extended
Logger interface.
>> 
>> 
>> 
>> On Mon, Jan 27, 2014 at 5:29 AM, Scott Deboy <scott.deboy@gmail.com> wrote:
>> Is there a way to generate code/update the Levels enumeration so a new
>> Level class isn't required?
>> 
>> Would be great to be able to use logger.detail("Detail message");
>> 
>> Is that what you're thinking of, Remko?
>> 
>> On 1/26/14, Ralph Goers <ralph.goers@dslextreme.com> wrote:
>> > I haven’t done anything to directly do that. However, custom levels need to
>> > be mapped to the standard levels in several places. It would be simple to
>> > add support for that wherever you want it.  Level.StdLevel.getStdLevel() is
>> > the method used to do that.
>> >
>> > Ralph
>> >
>> > On Jan 26, 2014, at 7:45 AM, Scott Deboy <scott.deboy@gmail.com> wrote:
>> >
>> >> Are these serialization-wise going to be the same as standard levels?
>> >>
>> >> Receivers and apps like Chainsaw would benefit from not requiring the
>> >> originating level class be included in the classpath.
>> >>
>> >> I'm thinking about socketreceiver and to a lesser extent
>> >> logfilepatternreceiver.
>> >>
>> >> Scott
>> >> On Jan 26, 2014 7:28 AM, "Scott Deboy" <scott.deboy@gmail.com> wrote:
>> >> So I assume we could build on this by adding the ability to generate these
>> >> custom levels from the config, with no user provided class required?
>> >>
>> >>
>> >>
>> >> On Jan 26, 2014 12:58 AM, "Ralph Goers" <ralph.goers@dslextreme.com>
>> >> wrote:
>> >> >
>> >> > I have completed the work on custom levels.  It uses a variation of
>> >> > Nick’s “extensible enum” class.  The major difference with what
he
>> >> > proposed is that the custom enums must be declared in a class annotated
>> >> > with @Plugin(name=“xxxx” category=“Level”) for them to be usable
during
>> >> > configuration.
>> >> >
>> >> > Are their any objections to me checking this in?  I’ll be doing the
>> >> > commit at around noon Pacific Daylight Time if I don’t hear any.
>> >> >
>> >> > Ralph
>> >> >
>> >> >
>> >> >
>> >> > On Jan 25, 2014, at 7:08 AM, Ralph Goers <Ralph.Goers@dslextreme.com>
>> >> > wrote:
>> >> >
>> >> >> I am working on the implementation of custom levels now.  I should
have
>> >> >> it done today.
>> >> >>
>> >> >> Ralph
>> >> >>
>> >> >> On Jan 24, 2014, at 7:07 PM, Remko Popma <remko.popma@gmail.com>
>> >> >> wrote:
>> >> >>
>> >> >>> What is the best way to make progress on the custom levels
>> >> >>> implementation?
>> >> >>>
>> >> >>> Do we re-open LOG4J-41 or start a fresh Jira ticket? For
>> >> >>> implementation ideas, do we attach files to Jira, or create
a branch?
>> >> >>>
>> >> >>> Remko
>> >> >>>
>> >> >>> On Saturday, January 25, 2014, Gary Gregory <garydgregory@gmail.com>
>> >> >>> wrote:
>> >> >>>>
>> >> >>>> On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma <remko.popma@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
>> >> >>>>> <garydgregory@gmail.com> wrote:
>> >> >>>>>>
>> >> >>>>>> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma
>> >> >>>>>> <remko.popma@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 <garydgregory@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 co
>> >> >>>>
>> >> >>>>
>> >> >>>>
>> >> >>>>
>> >> >>>> --
>> >> >>>> E-Mail: garydgregory@gmail.com | ggregory@apache.org
>> >> >>>> Java Persistence with Hibernate, Second Edition
>> >> >>>> JUnit in Action, Second Edition
>> >> >>>> Spring Batch in Action
>> >> >>>> Blog: http://garygregory.wordpress.com
>> >> >>>> Home: http://garygregory.com/
>> >> >>>> Tweet! http://twitter.com/GaryGregory
>> >> >>
>> >> >>
>> >> >
>> >
>> >
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>> 
>> 
> 
> 
> 
> 
> -- 
> Matt Sicker <boards@gmail.com>


Mime
View raw message