Re: Enums and Custom Levels - completed.

2014-01-28 Thread Remko Popma
I was going to make the change but ran out of time...
No rush though, I just didn't want to forget about it and have it cause
issues later in the generated code. (I'll bring this - maintenance - up in
the other thread. )

On Wednesday, January 29, 2014, Ralph Goers
>
wrote:

> I can do it but it won't be for another 8 hrs or so. If you need it sooner
> go ahead.
>
> Sent from my iPad
>
> On Jan 28, 2014, at 9:00 AM, Remko Popma  wrote:
>
> Who will make this change (getOrCreateLevel -> forName) ?
> I'm asking because I'm calling this method in the generated wrapper source
> code...
>
>
> On Mon, Jan 27, 2014 at 12:55 PM, Nick Williams <
> nicho...@nicholaswilliams.net> wrote:
>
> Okay. I'm good with "forName," then.
>
> N
>
> On Jan 26, 2014, at 9:51 PM, Ralph Goers wrote:
>
> I disagree - you are getting the Level that matches the name, so forName
> does describe what is happening.
>
> See the Javadoc on the second question.  The intValue is ignored unless
> the Level is created.  Yes, that could lead to some problems if there are
> conflicts, but I think returning the registered level is better than
> throwing an exception.
>
> Ralph
>
> On Jan 26, 2014, at 7:46 PM, Nick Williams 
> wrote:
>
> Level.forName wouldn't work--it's not just "for name," it's for the name
> /and/ the level. But it must be unique by the name.
>
> For that matter, what are we to do in the following situation?
>
> Level.getOrCreate("DIAG", 150);
> ...
> Level.getOrCreate("DIAG", 250);
>
> They're not going to get what they expect in both cases.
>
> Nick
>
> On Jan 26, 2014, at 9:28 PM, Matt Sicker wrote:
>
> How about Level.forName()?
>
>
> On 26 January 2014 21:06, Ralph Goers  wrote:
>
> No objections on spawning a separate thread for discussion 2.
>
> I also am not in love with the method name but it does describe what it
> does.  If anyone has any ideas on a better name please suggest it (we are
> talking about the getOrCreateLevel method name).
>
> Ralph
>
> On Jan 26, 2014, at 6:59 PM, Nick Williams 
> wrote:
>
> There are two separate discussions going on here, so it's easy to get
> lost. We should probably split discussions again.
>
> Discussion 1: The finer details of custom levels. I'm fine with using a
> static factory method and making the constructor private, but I'm not a big
> fan of the name. Just sounds awkward. Unfortunately, I can't come up with
> anything better.
>
> Discussion 2: A wrapper / extended interface for logging using these
> custom levels. Yes, Paul, users can just do this:
>
> logger.log(MyCustomLevels.LEVEL1, "message");
>
> That is already supported by making Level extensible. However, some on the
> team have expressed a desire to make it even easier. Given hypothetical
> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you
> call it:
>
> logger.note("message");
> logger.diag("message");
> etc.
>
> We're discussing options to make this possible. However, it is not a
> requirement to enable custom levels. Custom levels are now already possible.
>
> Any objections to breaking discussion 2 off into another thread?
>
> Nick
>
> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>
> I got lost in the discussion. Can someone please clarify... Is the custom
> logging interface a nice-to-have or a requirement of the system?
>
> I was hoping
>
>


Re: Enums and Custom Levels - completed.

2014-01-28 Thread Ralph Goers
I can do it but it won't be for another 8 hrs or so. If you need it sooner go 
ahead.

Sent from my iPad

> On Jan 28, 2014, at 9:00 AM, Remko Popma  wrote:
> 
> Who will make this change (getOrCreateLevel -> forName) ?
> I'm asking because I'm calling this method in the generated wrapper source 
> code...
> 
> 
>> On Mon, Jan 27, 2014 at 12:55 PM, Nick Williams 
>>  wrote:
>> Okay. I'm good with "forName," then.
>> 
>> N
>> 
>>> On Jan 26, 2014, at 9:51 PM, Ralph Goers wrote:
>>> 
>>> I disagree - you are getting the Level that matches the name, so forName 
>>> does describe what is happening.
>>> 
>>> See the Javadoc on the second question.  The intValue is ignored unless the 
>>> Level is created.  Yes, that could lead to some problems if there are 
>>> conflicts, but I think returning the registered level is better than 
>>> throwing an exception.
>>> 
>>> Ralph
>>> 
 On Jan 26, 2014, at 7:46 PM, Nick Williams  
 wrote:
 
 Level.forName wouldn't work--it's not just "for name," it's for the name 
 /and/ the level. But it must be unique by the name.
 
 For that matter, what are we to do in the following situation?
 
 Level.getOrCreate("DIAG", 150);
 ...
 Level.getOrCreate("DIAG", 250);
 
 They're not going to get what they expect in both cases.
 
 Nick
 
> On Jan 26, 2014, at 9:28 PM, Matt Sicker wrote:
> 
> How about Level.forName()?
> 
> 
>> On 26 January 2014 21:06, Ralph Goers  wrote:
>> No objections on spawning a separate thread for discussion 2. 
>> 
>> I also am not in love with the method name but it does describe what it 
>> does.  If anyone has any ideas on a better name please suggest it (we 
>> are talking about the getOrCreateLevel method name).
>> 
>> Ralph
>> 
>>> On Jan 26, 2014, at 6:59 PM, Nick Williams 
>>>  wrote:
>>> 
>>> There are two separate discussions going on here, so it's easy to get 
>>> lost. We should probably split discussions again.
>>> 
>>> Discussion 1: The finer details of custom levels. I'm fine with using a 
>>> static factory method and making the constructor private, but I'm not a 
>>> big fan of the name. Just sounds awkward. Unfortunately, I can't come 
>>> up with anything better.
>>> 
>>> Discussion 2: A wrapper / extended interface for logging using these 
>>> custom levels. Yes, Paul, users can just do this:
>>> 
>>> logger.log(MyCustomLevels.LEVEL1, "message");
>>> 
>>> That is already supported by making Level extensible. However, some on 
>>> the team have expressed a desire to make it even easier. Given 
>>> hypothetical custom levels DIAG and NOTE, the following would be a 
>>> "nice-to-have" as you call it:
>>> 
>>> logger.note("message");
>>> logger.diag("message");
>>> etc.
>>> 
>>> We're discussing options to make this possible. However, it is not a 
>>> requirement to enable custom levels. Custom levels are now already 
>>> possible.
>>> 
>>> Any objections to breaking discussion 2 off into another thread?
>>> 
>>> Nick
>>> 
 On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
 
 I got lost in the discussion. Can someone please clarify... Is the 
 custom logging interface a nice-to-have or a requirement of the system?
 
 I was hoping simply someone could write this (pseudocode below):
 logger.log(MyCustomLevels.LEVEL1, "message");
 
 ...so no different interface should be required, right? Can't someone 
 just pass in their log level directly without using one of the 
 named-log-level convenience methods?
 
 
> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
> Now Level can't be used in an annotation. Since it supports string 
> names for levels, should I just use Level.toLevel?
> 
> 
>> On 26 January 2014 19:55, Ralph Goers  
>> wrote:
>> I think I must be misunderstanding the part about “If those levels 
>> were added…”.  I don’t understand how a level can be added to a 
>> class from the config such that it is usable by a programmer at 
>> compile time.
>> 
>> Ralph
>> 
>>> On Jan 26, 2014, at 5:24 PM, Scott Deboy  
>>> wrote:
>>> 
>>> Couldn't we no-op instead of throw if the same identical level were 
>>> registered?
>>> 
>>> If those levels were then added to the same custom level class from 
>>> the config, could we use that single class in the logger calls?
 On Jan 26, 2014 5:15 PM, "Ralph Goers" 
  wrote:
 I am certain I could create a LevelPlugin that would allow you to 
 define one or more Levels in the configuration, but to use that 
 Level t

Re: Enums and Custom Levels - completed.

2014-01-28 Thread Remko Popma
Who will make this change (getOrCreateLevel -> forName) ?
I'm asking because I'm calling this method in the generated wrapper source
code...


On Mon, Jan 27, 2014 at 12:55 PM, Nick Williams <
nicho...@nicholaswilliams.net> wrote:

> Okay. I'm good with "forName," then.
>
> N
>
> On Jan 26, 2014, at 9:51 PM, Ralph Goers wrote:
>
> I disagree - you are getting the Level that matches the name, so forName
> does describe what is happening.
>
> See the Javadoc on the second question.  The intValue is ignored unless
> the Level is created.  Yes, that could lead to some problems if there are
> conflicts, but I think returning the registered level is better than
> throwing an exception.
>
> Ralph
>
> On Jan 26, 2014, at 7:46 PM, Nick Williams 
> wrote:
>
> Level.forName wouldn't work--it's not just "for name," it's for the name
> /and/ the level. But it must be unique by the name.
>
> For that matter, what are we to do in the following situation?
>
> Level.getOrCreate("DIAG", 150);
> ...
> Level.getOrCreate("DIAG", 250);
>
> They're not going to get what they expect in both cases.
>
> Nick
>
> On Jan 26, 2014, at 9:28 PM, Matt Sicker wrote:
>
> How about Level.forName()?
>
>
> On 26 January 2014 21:06, Ralph Goers  wrote:
>
>> No objections on spawning a separate thread for discussion 2.
>>
>> I also am not in love with the method name but it does describe what it
>> does.  If anyone has any ideas on a better name please suggest it (we are
>> talking about the getOrCreateLevel method name).
>>
>> Ralph
>>
>> On Jan 26, 2014, at 6:59 PM, Nick Williams 
>> wrote:
>>
>> There are two separate discussions going on here, so it's easy to get
>> lost. We should probably split discussions again.
>>
>> Discussion 1: The finer details of custom levels. I'm fine with using a
>> static factory method and making the constructor private, but I'm not a big
>> fan of the name. Just sounds awkward. Unfortunately, I can't come up with
>> anything better.
>>
>> Discussion 2: A wrapper / extended interface for logging using these
>> custom levels. Yes, Paul, users can just do this:
>>
>> logger.log(MyCustomLevels.LEVEL1, "message");
>>
>> That is already supported by making Level extensible. However, some on
>> the team have expressed a desire to make it even easier. Given hypothetical
>> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you
>> call it:
>>
>> logger.note("message");
>> logger.diag("message");
>> etc.
>>
>> We're discussing options to make this possible. However, it is not a
>> requirement to enable custom levels. Custom levels are now already possible.
>>
>> Any objections to breaking discussion 2 off into another thread?
>>
>> Nick
>>
>> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>>
>> I got lost in the discussion. Can someone please clarify... Is the custom
>> logging interface a nice-to-have or a requirement of the system?
>>
>> I was hoping simply someone could write this (pseudocode below):
>> logger.log(MyCustomLevels.LEVEL1, "message");
>>
>> ...so no different interface should be required, right? Can't someone
>> just pass in their log level directly without using one of the
>> named-log-level convenience methods?
>>
>>
>> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>>
>>> Now Level can't be used in an annotation. Since it supports string names
>>> for levels, should I just use Level.toLevel?
>>>
>>>
>>> On 26 January 2014 19:55, Ralph Goers wrote:
>>>
 I think I must be misunderstanding the part about "If those levels were
 added...".  I don't understand how a level can be added to a class from the
 config such that it is usable by a programmer at compile time.

 Ralph

 On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:

 Couldn't we no-op instead of throw if the same identical level were
 registered?

 If those levels were then added to the same custom level class from the
 config, could we use that single class in the logger calls?
  On Jan 26, 2014 5:15 PM, "Ralph Goers" 
 wrote:

> I am certain I could create a LevelPlugin that would allow you to
> define one or more Levels in the configuration, but to use that Level the
> user would have to code:
>
> logger.log(Level.toLevel("DIAG"), "hello world");
>
> In order to directly reference the level it has to be declared as a
> static from somewhere and it can only be instantiated a single time, so
> creating it from the configuration will prevent that.
>
> Ralph
>
> On Jan 26, 2014, at 4:03 PM, Scott Deboy 
> wrote:
>
> I have one goal: to remove my request for new built in levels by
> allowing the levels to be defined strictly via configuration. I agree 
> there
> may be some hurdles but that's my goal.
>
> I'd like to avoid the requirement that users provide their own level
> implementation or use a different API.
>
> Scott
>
>>
>>
>

Re: Enums and Custom Levels - completed.

2014-01-27 Thread Nick Williams
This part of the conversation should actually be happening in the "Using Custom 
Levels with a Custom/Wrapper Interface" thread.

Nick

On Jan 27, 2014, at 12:17 PM, Gary Gregory wrote:

> Yes that's the idea. 
> 
> Gary
> 
> 
>  Original message 
> From: Ralph Goers 
> Date:01/27/2014 11:19 (GMT-05:00) 
> To: Log4J Developers List 
> Subject: Re: Enums and Custom Levels - completed. 
> 
> If the user creates a custom Logger Wrapper then they can just code against 
> that and not use an interface, correct?
> 
> Ralph
> 
> On Jan 27, 2014, at 6:40 AM, Nick Williams  
> wrote:
> 
>> Wrapping a logger /implementation/ is fine. But the user needs an 
>> /interface/ to program against. That interface should extend Logger rather 
>> than re-define all of Logger's methods.
>> 
>> Nick
>> 
>> On Jan 27, 2014, at 8:24 AM, Gary Gregory wrote:
>> 
>>> Please note that in the case of domain specific logging (DSL!), I do not 
>>> want to extend, I want to wrap a logger. See my DEFCON example.
>>> 
>>> Gary
>>> 
>>> 
>>> On Sun, Jan 26, 2014 at 6:51 PM, Nick Williams 
>>>  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 getCustomLogger(Class loggerClass)
>>>  T getCustomLogger(Class loggerClass, Class)
>>>  T getCustomLogger(Class loggerClass, Class, 
>>> MessageFactory)
>>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>>  T getCustomLogger(Class loggerClass, Object)
>>>  T getCustomLogger(Class loggerClass, Object, 
>>> MessageFactory)
>>>  T getCustomLogger(Class loggerClass, String)
>>>  T getCustomLogger(Class 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"  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  

Re: Enums and Custom Levels - completed.

2014-01-27 Thread Gary Gregory
Yes that's the idea. 

Gary

 Original message 
From: Ralph Goers  
Date:01/27/2014  11:19  (GMT-05:00) 
To: Log4J Developers List  
Subject: Re: Enums and Custom Levels - completed. 

If the user creates a custom Logger Wrapper then they can just code against 
that and not use an interface, correct?

Ralph

On Jan 27, 2014, at 6:40 AM, Nick Williams  
wrote:

Wrapping a logger /implementation/ is fine. But the user needs an /interface/ 
to program against. That interface should extend Logger rather than re-define 
all of Logger's methods.

Nick

On Jan 27, 2014, at 8:24 AM, Gary Gregory wrote:

Please note that in the case of domain specific logging (DSL!), I do not want 
to extend, I want to wrap a logger. See my DEFCON example.

Gary


On Sun, Jan 26, 2014 at 6:51 PM, Nick Williams  
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 getCustomLogger(Class loggerClass)
 T getCustomLogger(Class loggerClass, Class)
 T getCustomLogger(Class loggerClass, Class, 
MessageFactory)
 T getCustomLogger(Class loggerClass, MessageFactory)
 T getCustomLogger(Class loggerClass, Object)
 T getCustomLogger(Class loggerClass, Object, 
MessageFactory)
 T getCustomLogger(Class loggerClass, String)
 T getCustomLogger(Class 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"  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  element, with 
sub-elements like ... 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  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  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  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"  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?
>>
>>
>>
&

Re: Enums and Custom Levels - completed.

2014-01-27 Thread Ralph Goers
If the user creates a custom Logger Wrapper then they can just code against 
that and not use an interface, correct?

Ralph

On Jan 27, 2014, at 6:40 AM, Nick Williams  
wrote:

> Wrapping a logger /implementation/ is fine. But the user needs an /interface/ 
> to program against. That interface should extend Logger rather than re-define 
> all of Logger's methods.
> 
> Nick
> 
> On Jan 27, 2014, at 8:24 AM, Gary Gregory wrote:
> 
>> Please note that in the case of domain specific logging (DSL!), I do not 
>> want to extend, I want to wrap a logger. See my DEFCON example.
>> 
>> Gary
>> 
>> 
>> On Sun, Jan 26, 2014 at 6:51 PM, Nick Williams 
>>  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 getCustomLogger(Class loggerClass)
>>  T getCustomLogger(Class loggerClass, Class)
>>  T getCustomLogger(Class loggerClass, Class, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>  T getCustomLogger(Class loggerClass, Object)
>>  T getCustomLogger(Class loggerClass, Object, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, String)
>>  T getCustomLogger(Class 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"  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  
>>> element, with sub-elements like ... 
>>> 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  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  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  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"  wrote:
>>> >> So I assume we could build on this by adding the ability to generate 
>>> >> these
>>> >> custom levels from the config, with no user pro

Re: Enums and Custom Levels - completed.

2014-01-27 Thread Nick Williams
Wrapping a logger /implementation/ is fine. But the user needs an /interface/ 
to program against. That interface should extend Logger rather than re-define 
all of Logger's methods.

Nick

On Jan 27, 2014, at 8:24 AM, Gary Gregory wrote:

> Please note that in the case of domain specific logging (DSL!), I do not want 
> to extend, I want to wrap a logger. See my DEFCON example.
> 
> Gary
> 
> 
> On Sun, Jan 26, 2014 at 6:51 PM, Nick Williams 
>  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 getCustomLogger(Class loggerClass)
>  T getCustomLogger(Class loggerClass, Class)
>  T getCustomLogger(Class loggerClass, Class, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, MessageFactory)
>  T getCustomLogger(Class loggerClass, Object)
>  T getCustomLogger(Class loggerClass, Object, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, String)
>  T getCustomLogger(Class 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"  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  
>> element, with sub-elements like ... 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  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  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  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"  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" 
>> >> 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

Re: Enums and Custom Levels - completed.

2014-01-27 Thread Gary Gregory
Please note that in the case of domain specific logging (DSL!), I do not
want to extend, I want to wrap a logger. See my DEFCON example.

Gary


On Sun, Jan 26, 2014 at 6:51 PM, Nick Williams <
nicho...@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 getCustomLogger(Class loggerClass)
>  T getCustomLogger(Class loggerClass, Class)
>  T getCustomLogger(Class loggerClass, Class,
> MessageFactory)
>  T getCustomLogger(Class loggerClass, MessageFactory)
>  T getCustomLogger(Class loggerClass, Object)
>  T getCustomLogger(Class loggerClass, Object,
> MessageFactory)
>  T getCustomLogger(Class loggerClass, String)
>  T getCustomLogger(Class 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"  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 
>> element, with sub-elements like ...
>> 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 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  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 
>>> 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"  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" 
>>> >> 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=“” category=“Level”) for them to be usable
>>> during
>>> >> > configuration.
>>> >> >
>>> >> > Are their any objections to me checking this in?  I’ll be doing the
>>> >> > comm

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
Okay. I'm good with "forName," then.

N

On Jan 26, 2014, at 9:51 PM, Ralph Goers wrote:

> I disagree - you are getting the Level that matches the name, so forName does 
> describe what is happening.
> 
> See the Javadoc on the second question.  The intValue is ignored unless the 
> Level is created.  Yes, that could lead to some problems if there are 
> conflicts, but I think returning the registered level is better than throwing 
> an exception.
> 
> Ralph
> 
> On Jan 26, 2014, at 7:46 PM, Nick Williams  
> wrote:
> 
>> Level.forName wouldn't work--it's not just "for name," it's for the name 
>> /and/ the level. But it must be unique by the name.
>> 
>> For that matter, what are we to do in the following situation?
>> 
>> Level.getOrCreate("DIAG", 150);
>> ...
>> Level.getOrCreate("DIAG", 250);
>> 
>> They're not going to get what they expect in both cases.
>> 
>> Nick
>> 
>> On Jan 26, 2014, at 9:28 PM, Matt Sicker wrote:
>> 
>>> How about Level.forName()?
>>> 
>>> 
>>> On 26 January 2014 21:06, Ralph Goers  wrote:
>>> No objections on spawning a separate thread for discussion 2. 
>>> 
>>> I also am not in love with the method name but it does describe what it 
>>> does.  If anyone has any ideas on a better name please suggest it (we are 
>>> talking about the getOrCreateLevel method name).
>>> 
>>> Ralph
>>> 
>>> On Jan 26, 2014, at 6:59 PM, Nick Williams  
>>> wrote:
>>> 
 There are two separate discussions going on here, so it's easy to get 
 lost. We should probably split discussions again.
 
 Discussion 1: The finer details of custom levels. I'm fine with using a 
 static factory method and making the constructor private, but I'm not a 
 big fan of the name. Just sounds awkward. Unfortunately, I can't come up 
 with anything better.
 
 Discussion 2: A wrapper / extended interface for logging using these 
 custom levels. Yes, Paul, users can just do this:
 
 logger.log(MyCustomLevels.LEVEL1, "message");
 
 That is already supported by making Level extensible. However, some on the 
 team have expressed a desire to make it even easier. Given hypothetical 
 custom levels DIAG and NOTE, the following would be a "nice-to-have" as 
 you call it:
 
 logger.note("message");
 logger.diag("message");
 etc.
 
 We're discussing options to make this possible. However, it is not a 
 requirement to enable custom levels. Custom levels are now already 
 possible.
 
 Any objections to breaking discussion 2 off into another thread?
 
 Nick
 
 On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
 
> I got lost in the discussion. Can someone please clarify... Is the custom 
> logging interface a nice-to-have or a requirement of the system?
> 
> I was hoping simply someone could write this (pseudocode below):
> logger.log(MyCustomLevels.LEVEL1, "message");
> 
> ...so no different interface should be required, right? Can't someone 
> just pass in their log level directly without using one of the 
> named-log-level convenience methods?
> 
> 
> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
> Now Level can't be used in an annotation. Since it supports string names 
> for levels, should I just use Level.toLevel?
> 
> 
> On 26 January 2014 19:55, Ralph Goers  wrote:
> I think I must be misunderstanding the part about “If those levels were 
> added…”.  I don’t understand how a level can be added to a class from the 
> config such that it is usable by a programmer at compile time.
> 
> Ralph
> 
> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
> 
>> Couldn't we no-op instead of throw if the same identical level were 
>> registered?
>> 
>> If those levels were then added to the same custom level class from the 
>> config, could we use that single class in the logger calls?
>> On Jan 26, 2014 5:15 PM, "Ralph Goers"  
>> wrote:
>> I am certain I could create a LevelPlugin that would allow you to define 
>> one or more Levels in the configuration, but to use that Level the user 
>> would have to code:
>> 
>> logger.log(Level.toLevel(“DIAG”), “hello world”);
>> 
>> In order to directly reference the level it has to be declared as a 
>> static from somewhere and it can only be instantiated a single time, so 
>> creating it from the configuration will prevent that.
>> 
>> Ralph
>> 
>> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
>> 
>>> I have one goal: to remove my request for new built in levels by 
>>> allowing the levels to be defined strictly via configuration. I agree 
>>> there may be some hurdles but that's my goal.
>>> 
>>> I'd like to avoid the requirement that users provide their own level 
>>> implementation or use a different API.
>>> 
>>> Scott
>>> 
>> 
>

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I disagree - you are getting the Level that matches the name, so forName does 
describe what is happening.

See the Javadoc on the second question.  The intValue is ignored unless the 
Level is created.  Yes, that could lead to some problems if there are 
conflicts, but I think returning the registered level is better than throwing 
an exception.

Ralph

On Jan 26, 2014, at 7:46 PM, Nick Williams  
wrote:

> Level.forName wouldn't work--it's not just "for name," it's for the name 
> /and/ the level. But it must be unique by the name.
> 
> For that matter, what are we to do in the following situation?
> 
> Level.getOrCreate("DIAG", 150);
> ...
> Level.getOrCreate("DIAG", 250);
> 
> They're not going to get what they expect in both cases.
> 
> Nick
> 
> On Jan 26, 2014, at 9:28 PM, Matt Sicker wrote:
> 
>> How about Level.forName()?
>> 
>> 
>> On 26 January 2014 21:06, Ralph Goers  wrote:
>> No objections on spawning a separate thread for discussion 2. 
>> 
>> I also am not in love with the method name but it does describe what it 
>> does.  If anyone has any ideas on a better name please suggest it (we are 
>> talking about the getOrCreateLevel method name).
>> 
>> Ralph
>> 
>> On Jan 26, 2014, at 6:59 PM, Nick Williams  
>> wrote:
>> 
>>> There are two separate discussions going on here, so it's easy to get lost. 
>>> We should probably split discussions again.
>>> 
>>> Discussion 1: The finer details of custom levels. I'm fine with using a 
>>> static factory method and making the constructor private, but I'm not a big 
>>> fan of the name. Just sounds awkward. Unfortunately, I can't come up with 
>>> anything better.
>>> 
>>> Discussion 2: A wrapper / extended interface for logging using these custom 
>>> levels. Yes, Paul, users can just do this:
>>> 
>>> logger.log(MyCustomLevels.LEVEL1, "message");
>>> 
>>> That is already supported by making Level extensible. However, some on the 
>>> team have expressed a desire to make it even easier. Given hypothetical 
>>> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you 
>>> call it:
>>> 
>>> logger.note("message");
>>> logger.diag("message");
>>> etc.
>>> 
>>> We're discussing options to make this possible. However, it is not a 
>>> requirement to enable custom levels. Custom levels are now already possible.
>>> 
>>> Any objections to breaking discussion 2 off into another thread?
>>> 
>>> Nick
>>> 
>>> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>>> 
 I got lost in the discussion. Can someone please clarify... Is the custom 
 logging interface a nice-to-have or a requirement of the system?
 
 I was hoping simply someone could write this (pseudocode below):
 logger.log(MyCustomLevels.LEVEL1, "message");
 
 ...so no different interface should be required, right? Can't someone just 
 pass in their log level directly without using one of the named-log-level 
 convenience methods?
 
 
 On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
 Now Level can't be used in an annotation. Since it supports string names 
 for levels, should I just use Level.toLevel?
 
 
 On 26 January 2014 19:55, Ralph Goers  wrote:
 I think I must be misunderstanding the part about “If those levels were 
 added…”.  I don’t understand how a level can be added to a class from the 
 config such that it is usable by a programmer at compile time.
 
 Ralph
 
 On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
 
> Couldn't we no-op instead of throw if the same identical level were 
> registered?
> 
> If those levels were then added to the same custom level class from the 
> config, could we use that single class in the logger calls?
> On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
> I am certain I could create a LevelPlugin that would allow you to define 
> one or more Levels in the configuration, but to use that Level the user 
> would have to code:
> 
> logger.log(Level.toLevel(“DIAG”), “hello world”);
> 
> In order to directly reference the level it has to be declared as a 
> static from somewhere and it can only be instantiated a single time, so 
> creating it from the configuration will prevent that.
> 
> Ralph
> 
> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
> 
>> I have one goal: to remove my request for new built in levels by 
>> allowing the levels to be defined strictly via configuration. I agree 
>> there may be some hurdles but that's my goal.
>> 
>> I'd like to avoid the requirement that users provide their own level 
>> implementation or use a different API.
>> 
>> Scott
>> 
> 
 
 
 
 
 -- 
 Matt Sicker 
 
 
 
 -- 
 Cheers,
 Paul
>>> 
>> 
>> 
>> 
>> 
>> -- 
>> Matt Sicker 
> 



Re: Enums and Custom Levels - completed.

2014-01-26 Thread Matt Sicker
Perhaps if we called the priority or ordinal "power", then we'd have a
great time with the naming scheme?


On 26 January 2014 21:46, Nick Williams wrote:

> Level.forName wouldn't work--it's not just "for name," it's for the name
> /and/ the level. But it must be unique by the name.
>
> For that matter, what are we to do in the following situation?
>
> Level.getOrCreate("DIAG", 150);
> ...
> Level.getOrCreate("DIAG", 250);
>
> They're not going to get what they expect in both cases.
>
> Nick
>
>
> On Jan 26, 2014, at 9:28 PM, Matt Sicker wrote:
>
> How about Level.forName()?
>
>
> On 26 January 2014 21:06, Ralph Goers  wrote:
>
>> No objections on spawning a separate thread for discussion 2.
>>
>> I also am not in love with the method name but it does describe what it
>> does.  If anyone has any ideas on a better name please suggest it (we are
>> talking about the getOrCreateLevel method name).
>>
>> Ralph
>>
>> On Jan 26, 2014, at 6:59 PM, Nick Williams 
>> wrote:
>>
>> There are two separate discussions going on here, so it's easy to get
>> lost. We should probably split discussions again.
>>
>> Discussion 1: The finer details of custom levels. I'm fine with using a
>> static factory method and making the constructor private, but I'm not a big
>> fan of the name. Just sounds awkward. Unfortunately, I can't come up with
>> anything better.
>>
>> Discussion 2: A wrapper / extended interface for logging using these
>> custom levels. Yes, Paul, users can just do this:
>>
>> logger.log(MyCustomLevels.LEVEL1, "message");
>>
>> That is already supported by making Level extensible. However, some on
>> the team have expressed a desire to make it even easier. Given hypothetical
>> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you
>> call it:
>>
>> logger.note("message");
>> logger.diag("message");
>> etc.
>>
>> We're discussing options to make this possible. However, it is not a
>> requirement to enable custom levels. Custom levels are now already possible.
>>
>> Any objections to breaking discussion 2 off into another thread?
>>
>> Nick
>>
>> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>>
>> I got lost in the discussion. Can someone please clarify... Is the custom
>> logging interface a nice-to-have or a requirement of the system?
>>
>> I was hoping simply someone could write this (pseudocode below):
>> logger.log(MyCustomLevels.LEVEL1, "message");
>>
>> ...so no different interface should be required, right? Can't someone
>> just pass in their log level directly without using one of the
>> named-log-level convenience methods?
>>
>>
>> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>>
>>> Now Level can't be used in an annotation. Since it supports string names
>>> for levels, should I just use Level.toLevel?
>>>
>>>
>>> On 26 January 2014 19:55, Ralph Goers wrote:
>>>
 I think I must be misunderstanding the part about “If those levels were
 added…”.  I don’t understand how a level can be added to a class from the
 config such that it is usable by a programmer at compile time.

 Ralph

 On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:

 Couldn't we no-op instead of throw if the same identical level were
 registered?

 If those levels were then added to the same custom level class from the
 config, could we use that single class in the logger calls?
  On Jan 26, 2014 5:15 PM, "Ralph Goers" 
 wrote:

> I am certain I could create a LevelPlugin that would allow you to
> define one or more Levels in the configuration, but to use that Level the
> user would have to code:
>
> logger.log(Level.toLevel(“DIAG”), “hello world”);
>
> In order to directly reference the level it has to be declared as a
> static from somewhere and it can only be instantiated a single time, so
> creating it from the configuration will prevent that.
>
> Ralph
>
> On Jan 26, 2014, at 4:03 PM, Scott Deboy 
> wrote:
>
> I have one goal: to remove my request for new built in levels by
> allowing the levels to be defined strictly via configuration. I agree 
> there
> may be some hurdles but that's my goal.
>
> I'd like to avoid the requirement that users provide their own level
> implementation or use a different API.
>
> Scott
>
>>
>>
>

>>>
>>>
>>> --
>>> Matt Sicker 
>>>
>>
>>
>>
>> --
>> Cheers,
>> Paul
>>
>>
>>
>>
>
>
> --
> Matt Sicker 
>
>
>


-- 
Matt Sicker 


Re: Enums and Custom Levels - completed.

2014-01-26 Thread Matt Sicker
I second my suggestion!


On 26 January 2014 21:44, Ralph Goers  wrote:

> My first gut reaction was confusion over Class.forName(). But then in
> thinking about it that name does behave a lot like what Class.forName()
> does, except with a Level.  So I think I do like it better than the current
> name.
>
> Any other thoughts or opinions?
>
> Ralph
>
>
> On Jan 26, 2014, at 7:28 PM, Matt Sicker  wrote:
>
> How about Level.forName()?
>
>
> On 26 January 2014 21:06, Ralph Goers  wrote:
>
>> No objections on spawning a separate thread for discussion 2.
>>
>> I also am not in love with the method name but it does describe what it
>> does.  If anyone has any ideas on a better name please suggest it (we are
>> talking about the getOrCreateLevel method name).
>>
>> Ralph
>>
>> On Jan 26, 2014, at 6:59 PM, Nick Williams 
>> wrote:
>>
>> There are two separate discussions going on here, so it's easy to get
>> lost. We should probably split discussions again.
>>
>> Discussion 1: The finer details of custom levels. I'm fine with using a
>> static factory method and making the constructor private, but I'm not a big
>> fan of the name. Just sounds awkward. Unfortunately, I can't come up with
>> anything better.
>>
>> Discussion 2: A wrapper / extended interface for logging using these
>> custom levels. Yes, Paul, users can just do this:
>>
>> logger.log(MyCustomLevels.LEVEL1, "message");
>>
>> That is already supported by making Level extensible. However, some on
>> the team have expressed a desire to make it even easier. Given hypothetical
>> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you
>> call it:
>>
>> logger.note("message");
>> logger.diag("message");
>> etc.
>>
>> We're discussing options to make this possible. However, it is not a
>> requirement to enable custom levels. Custom levels are now already possible.
>>
>> Any objections to breaking discussion 2 off into another thread?
>>
>> Nick
>>
>> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>>
>> I got lost in the discussion. Can someone please clarify... Is the custom
>> logging interface a nice-to-have or a requirement of the system?
>>
>> I was hoping simply someone could write this (pseudocode below):
>> logger.log(MyCustomLevels.LEVEL1, "message");
>>
>> ...so no different interface should be required, right? Can't someone
>> just pass in their log level directly without using one of the
>> named-log-level convenience methods?
>>
>>
>> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>>
>>> Now Level can't be used in an annotation. Since it supports string names
>>> for levels, should I just use Level.toLevel?
>>>
>>>
>>> On 26 January 2014 19:55, Ralph Goers wrote:
>>>
 I think I must be misunderstanding the part about “If those levels were
 added…”.  I don’t understand how a level can be added to a class from the
 config such that it is usable by a programmer at compile time.

 Ralph

 On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:

 Couldn't we no-op instead of throw if the same identical level were
 registered?

 If those levels were then added to the same custom level class from the
 config, could we use that single class in the logger calls?
  On Jan 26, 2014 5:15 PM, "Ralph Goers" 
 wrote:

> I am certain I could create a LevelPlugin that would allow you to
> define one or more Levels in the configuration, but to use that Level the
> user would have to code:
>
> logger.log(Level.toLevel(“DIAG”), “hello world”);
>
> In order to directly reference the level it has to be declared as a
> static from somewhere and it can only be instantiated a single time, so
> creating it from the configuration will prevent that.
>
> Ralph
>
> On Jan 26, 2014, at 4:03 PM, Scott Deboy 
> wrote:
>
> I have one goal: to remove my request for new built in levels by
> allowing the levels to be defined strictly via configuration. I agree 
> there
> may be some hurdles but that's my goal.
>
> I'd like to avoid the requirement that users provide their own level
> implementation or use a different API.
>
> Scott
>
>>
>>
>

>>>
>>>
>>> --
>>> Matt Sicker 
>>>
>>
>>
>>
>> --
>> Cheers,
>> Paul
>>
>>
>>
>>
>
>
> --
> Matt Sicker 
>
>
>


-- 
Matt Sicker 


Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
Level.forName wouldn't work--it's not just "for name," it's for the name /and/ 
the level. But it must be unique by the name.

For that matter, what are we to do in the following situation?

Level.getOrCreate("DIAG", 150);
...
Level.getOrCreate("DIAG", 250);

They're not going to get what they expect in both cases.

Nick

On Jan 26, 2014, at 9:28 PM, Matt Sicker wrote:

> How about Level.forName()?
> 
> 
> On 26 January 2014 21:06, Ralph Goers  wrote:
> No objections on spawning a separate thread for discussion 2. 
> 
> I also am not in love with the method name but it does describe what it does. 
>  If anyone has any ideas on a better name please suggest it (we are talking 
> about the getOrCreateLevel method name).
> 
> Ralph
> 
> On Jan 26, 2014, at 6:59 PM, Nick Williams  
> wrote:
> 
>> There are two separate discussions going on here, so it's easy to get lost. 
>> We should probably split discussions again.
>> 
>> Discussion 1: The finer details of custom levels. I'm fine with using a 
>> static factory method and making the constructor private, but I'm not a big 
>> fan of the name. Just sounds awkward. Unfortunately, I can't come up with 
>> anything better.
>> 
>> Discussion 2: A wrapper / extended interface for logging using these custom 
>> levels. Yes, Paul, users can just do this:
>> 
>> logger.log(MyCustomLevels.LEVEL1, "message");
>> 
>> That is already supported by making Level extensible. However, some on the 
>> team have expressed a desire to make it even easier. Given hypothetical 
>> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you 
>> call it:
>> 
>> logger.note("message");
>> logger.diag("message");
>> etc.
>> 
>> We're discussing options to make this possible. However, it is not a 
>> requirement to enable custom levels. Custom levels are now already possible.
>> 
>> Any objections to breaking discussion 2 off into another thread?
>> 
>> Nick
>> 
>> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>> 
>>> I got lost in the discussion. Can someone please clarify... Is the custom 
>>> logging interface a nice-to-have or a requirement of the system?
>>> 
>>> I was hoping simply someone could write this (pseudocode below):
>>> logger.log(MyCustomLevels.LEVEL1, "message");
>>> 
>>> ...so no different interface should be required, right? Can't someone just 
>>> pass in their log level directly without using one of the named-log-level 
>>> convenience methods?
>>> 
>>> 
>>> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>>> Now Level can't be used in an annotation. Since it supports string names 
>>> for levels, should I just use Level.toLevel?
>>> 
>>> 
>>> On 26 January 2014 19:55, Ralph Goers  wrote:
>>> I think I must be misunderstanding the part about “If those levels were 
>>> added…”.  I don’t understand how a level can be added to a class from the 
>>> config such that it is usable by a programmer at compile time.
>>> 
>>> Ralph
>>> 
>>> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
>>> 
 Couldn't we no-op instead of throw if the same identical level were 
 registered?
 
 If those levels were then added to the same custom level class from the 
 config, could we use that single class in the logger calls?
 On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
 I am certain I could create a LevelPlugin that would allow you to define 
 one or more Levels in the configuration, but to use that Level the user 
 would have to code:
 
 logger.log(Level.toLevel(“DIAG”), “hello world”);
 
 In order to directly reference the level it has to be declared as a static 
 from somewhere and it can only be instantiated a single time, so creating 
 it from the configuration will prevent that.
 
 Ralph
 
 On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
 
> I have one goal: to remove my request for new built in levels by allowing 
> the levels to be defined strictly via configuration. I agree there may be 
> some hurdles but that's my goal.
> 
> I'd like to avoid the requirement that users provide their own level 
> implementation or use a different API.
> 
> Scott
> 
 
>>> 
>>> 
>>> 
>>> 
>>> -- 
>>> Matt Sicker 
>>> 
>>> 
>>> 
>>> -- 
>>> Cheers,
>>> Paul
>> 
> 
> 
> 
> 
> -- 
> Matt Sicker 



Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
My first gut reaction was confusion over Class.forName(). But then in thinking 
about it that name does behave a lot like what Class.forName() does, except 
with a Level.  So I think I do like it better than the current name.  

Any other thoughts or opinions?

Ralph


On Jan 26, 2014, at 7:28 PM, Matt Sicker  wrote:

> How about Level.forName()?
> 
> 
> On 26 January 2014 21:06, Ralph Goers  wrote:
> No objections on spawning a separate thread for discussion 2. 
> 
> I also am not in love with the method name but it does describe what it does. 
>  If anyone has any ideas on a better name please suggest it (we are talking 
> about the getOrCreateLevel method name).
> 
> Ralph
> 
> On Jan 26, 2014, at 6:59 PM, Nick Williams  
> wrote:
> 
>> There are two separate discussions going on here, so it's easy to get lost. 
>> We should probably split discussions again.
>> 
>> Discussion 1: The finer details of custom levels. I'm fine with using a 
>> static factory method and making the constructor private, but I'm not a big 
>> fan of the name. Just sounds awkward. Unfortunately, I can't come up with 
>> anything better.
>> 
>> Discussion 2: A wrapper / extended interface for logging using these custom 
>> levels. Yes, Paul, users can just do this:
>> 
>> logger.log(MyCustomLevels.LEVEL1, "message");
>> 
>> That is already supported by making Level extensible. However, some on the 
>> team have expressed a desire to make it even easier. Given hypothetical 
>> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you 
>> call it:
>> 
>> logger.note("message");
>> logger.diag("message");
>> etc.
>> 
>> We're discussing options to make this possible. However, it is not a 
>> requirement to enable custom levels. Custom levels are now already possible.
>> 
>> Any objections to breaking discussion 2 off into another thread?
>> 
>> Nick
>> 
>> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>> 
>>> I got lost in the discussion. Can someone please clarify... Is the custom 
>>> logging interface a nice-to-have or a requirement of the system?
>>> 
>>> I was hoping simply someone could write this (pseudocode below):
>>> logger.log(MyCustomLevels.LEVEL1, "message");
>>> 
>>> ...so no different interface should be required, right? Can't someone just 
>>> pass in their log level directly without using one of the named-log-level 
>>> convenience methods?
>>> 
>>> 
>>> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>>> Now Level can't be used in an annotation. Since it supports string names 
>>> for levels, should I just use Level.toLevel?
>>> 
>>> 
>>> On 26 January 2014 19:55, Ralph Goers  wrote:
>>> I think I must be misunderstanding the part about “If those levels were 
>>> added…”.  I don’t understand how a level can be added to a class from the 
>>> config such that it is usable by a programmer at compile time.
>>> 
>>> Ralph
>>> 
>>> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
>>> 
 Couldn't we no-op instead of throw if the same identical level were 
 registered?
 
 If those levels were then added to the same custom level class from the 
 config, could we use that single class in the logger calls?
 On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
 I am certain I could create a LevelPlugin that would allow you to define 
 one or more Levels in the configuration, but to use that Level the user 
 would have to code:
 
 logger.log(Level.toLevel(“DIAG”), “hello world”);
 
 In order to directly reference the level it has to be declared as a static 
 from somewhere and it can only be instantiated a single time, so creating 
 it from the configuration will prevent that.
 
 Ralph
 
 On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
 
> I have one goal: to remove my request for new built in levels by allowing 
> the levels to be defined strictly via configuration. I agree there may be 
> some hurdles but that's my goal.
> 
> I'd like to avoid the requirement that users provide their own level 
> implementation or use a different API.
> 
> Scott
> 
 
>>> 
>>> 
>>> 
>>> 
>>> -- 
>>> Matt Sicker 
>>> 
>>> 
>>> 
>>> -- 
>>> Cheers,
>>> Paul
>> 
> 
> 
> 
> 
> -- 
> Matt Sicker 



Re: Enums and Custom Levels - completed.

2014-01-26 Thread Matt Sicker
How about Level.forName()?


On 26 January 2014 21:06, Ralph Goers  wrote:

> No objections on spawning a separate thread for discussion 2.
>
> I also am not in love with the method name but it does describe what it
> does.  If anyone has any ideas on a better name please suggest it (we are
> talking about the getOrCreateLevel method name).
>
> Ralph
>
> On Jan 26, 2014, at 6:59 PM, Nick Williams 
> wrote:
>
> There are two separate discussions going on here, so it's easy to get
> lost. We should probably split discussions again.
>
> Discussion 1: The finer details of custom levels. I'm fine with using a
> static factory method and making the constructor private, but I'm not a big
> fan of the name. Just sounds awkward. Unfortunately, I can't come up with
> anything better.
>
> Discussion 2: A wrapper / extended interface for logging using these
> custom levels. Yes, Paul, users can just do this:
>
> logger.log(MyCustomLevels.LEVEL1, "message");
>
> That is already supported by making Level extensible. However, some on the
> team have expressed a desire to make it even easier. Given hypothetical
> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you
> call it:
>
> logger.note("message");
> logger.diag("message");
> etc.
>
> We're discussing options to make this possible. However, it is not a
> requirement to enable custom levels. Custom levels are now already possible.
>
> Any objections to breaking discussion 2 off into another thread?
>
> Nick
>
> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
>
> I got lost in the discussion. Can someone please clarify... Is the custom
> logging interface a nice-to-have or a requirement of the system?
>
> I was hoping simply someone could write this (pseudocode below):
> logger.log(MyCustomLevels.LEVEL1, "message");
>
> ...so no different interface should be required, right? Can't someone just
> pass in their log level directly without using one of the named-log-level
> convenience methods?
>
>
> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>
>> Now Level can't be used in an annotation. Since it supports string names
>> for levels, should I just use Level.toLevel?
>>
>>
>> On 26 January 2014 19:55, Ralph Goers  wrote:
>>
>>> I think I must be misunderstanding the part about “If those levels were
>>> added…”.  I don’t understand how a level can be added to a class from the
>>> config such that it is usable by a programmer at compile time.
>>>
>>> Ralph
>>>
>>> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
>>>
>>> Couldn't we no-op instead of throw if the same identical level were
>>> registered?
>>>
>>> If those levels were then added to the same custom level class from the
>>> config, could we use that single class in the logger calls?
>>>  On Jan 26, 2014 5:15 PM, "Ralph Goers" 
>>> wrote:
>>>
 I am certain I could create a LevelPlugin that would allow you to
 define one or more Levels in the configuration, but to use that Level the
 user would have to code:

 logger.log(Level.toLevel(“DIAG”), “hello world”);

 In order to directly reference the level it has to be declared as a
 static from somewhere and it can only be instantiated a single time, so
 creating it from the configuration will prevent that.

 Ralph

 On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:

 I have one goal: to remove my request for new built in levels by
 allowing the levels to be defined strictly via configuration. I agree there
 may be some hurdles but that's my goal.

 I'd like to avoid the requirement that users provide their own level
 implementation or use a different API.

 Scott

>
>

>>>
>>
>>
>> --
>> Matt Sicker 
>>
>
>
>
> --
> Cheers,
> Paul
>
>
>
>


-- 
Matt Sicker 


Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
No objections on spawning a separate thread for discussion 2. 

I also am not in love with the method name but it does describe what it does.  
If anyone has any ideas on a better name please suggest it (we are talking 
about the getOrCreateLevel method name).

Ralph

On Jan 26, 2014, at 6:59 PM, Nick Williams  
wrote:

> There are two separate discussions going on here, so it's easy to get lost. 
> We should probably split discussions again.
> 
> Discussion 1: The finer details of custom levels. I'm fine with using a 
> static factory method and making the constructor private, but I'm not a big 
> fan of the name. Just sounds awkward. Unfortunately, I can't come up with 
> anything better.
> 
> Discussion 2: A wrapper / extended interface for logging using these custom 
> levels. Yes, Paul, users can just do this:
> 
> logger.log(MyCustomLevels.LEVEL1, "message");
> 
> That is already supported by making Level extensible. However, some on the 
> team have expressed a desire to make it even easier. Given hypothetical 
> custom levels DIAG and NOTE, the following would be a "nice-to-have" as you 
> call it:
> 
> logger.note("message");
> logger.diag("message");
> etc.
> 
> We're discussing options to make this possible. However, it is not a 
> requirement to enable custom levels. Custom levels are now already possible.
> 
> Any objections to breaking discussion 2 off into another thread?
> 
> Nick
> 
> On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:
> 
>> I got lost in the discussion. Can someone please clarify... Is the custom 
>> logging interface a nice-to-have or a requirement of the system?
>> 
>> I was hoping simply someone could write this (pseudocode below):
>> logger.log(MyCustomLevels.LEVEL1, "message");
>> 
>> ...so no different interface should be required, right? Can't someone just 
>> pass in their log level directly without using one of the named-log-level 
>> convenience methods?
>> 
>> 
>> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>> Now Level can't be used in an annotation. Since it supports string names for 
>> levels, should I just use Level.toLevel?
>> 
>> 
>> On 26 January 2014 19:55, Ralph Goers  wrote:
>> I think I must be misunderstanding the part about “If those levels were 
>> added…”.  I don’t understand how a level can be added to a class from the 
>> config such that it is usable by a programmer at compile time.
>> 
>> Ralph
>> 
>> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
>> 
>>> Couldn't we no-op instead of throw if the same identical level were 
>>> registered?
>>> 
>>> If those levels were then added to the same custom level class from the 
>>> config, could we use that single class in the logger calls?
>>> On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
>>> I am certain I could create a LevelPlugin that would allow you to define 
>>> one or more Levels in the configuration, but to use that Level the user 
>>> would have to code:
>>> 
>>> logger.log(Level.toLevel(“DIAG”), “hello world”);
>>> 
>>> In order to directly reference the level it has to be declared as a static 
>>> from somewhere and it can only be instantiated a single time, so creating 
>>> it from the configuration will prevent that.
>>> 
>>> Ralph
>>> 
>>> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
>>> 
 I have one goal: to remove my request for new built in levels by allowing 
 the levels to be defined strictly via configuration. I agree there may be 
 some hurdles but that's my goal.
 
 I'd like to avoid the requirement that users provide their own level 
 implementation or use a different API.
 
 Scott
 
>>> 
>> 
>> 
>> 
>> 
>> -- 
>> Matt Sicker 
>> 
>> 
>> 
>> -- 
>> Cheers,
>> Paul
> 



Re: Enums and Custom Levels - completed.

2014-01-26 Thread Paul Benedict
If you break off into another thread, I'll be watching; I'll throw in my 2
cents on how to make a custom Logger interface once that occurs.


On Sun, Jan 26, 2014 at 9:01 PM, Ralph Goers wrote:

> Yes, logger.log(MyCustomLEvels.LEVEL1, “message”); works right now.  See
> the ExtendedLevels class in log4j-core test as an example on how to declare
> the level.
>
> I think several of us think that finding a way to make it easy to create
> extended logger methods would be very nice, but I don’t believe it is a
> requirement.
>
> Ralph
>
> On Jan 26, 2014, at 6:46 PM, Paul Benedict  wrote:
>
> I got lost in the discussion. Can someone please clarify... Is the custom
> logging interface a nice-to-have or a requirement of the system?
>
> I was hoping simply someone could write this (pseudocode below):
> logger.log(MyCustomLevels.LEVEL1, "message");
>
> ...so no different interface should be required, right? Can't someone just
> pass in their log level directly without using one of the named-log-level
> convenience methods?
>
>
> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
>
>> Now Level can't be used in an annotation. Since it supports string names
>> for levels, should I just use Level.toLevel?
>>
>>
>> On 26 January 2014 19:55, Ralph Goers  wrote:
>>
>>> I think I must be misunderstanding the part about “If those levels were
>>> added…”.  I don’t understand how a level can be added to a class from the
>>> config such that it is usable by a programmer at compile time.
>>>
>>> Ralph
>>>
>>> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
>>>
>>> Couldn't we no-op instead of throw if the same identical level were
>>> registered?
>>>
>>> If those levels were then added to the same custom level class from the
>>> config, could we use that single class in the logger calls?
>>>  On Jan 26, 2014 5:15 PM, "Ralph Goers" 
>>> wrote:
>>>
 I am certain I could create a LevelPlugin that would allow you to
 define one or more Levels in the configuration, but to use that Level the
 user would have to code:

 logger.log(Level.toLevel(“DIAG”), “hello world”);

 In order to directly reference the level it has to be declared as a
 static from somewhere and it can only be instantiated a single time, so
 creating it from the configuration will prevent that.

 Ralph

 On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:

 I have one goal: to remove my request for new built in levels by
 allowing the levels to be defined strictly via configuration. I agree there
 may be some hurdles but that's my goal.

 I'd like to avoid the requirement that users provide their own level
 implementation or use a different API.

 Scott

>
>

>>>
>>
>>
>> --
>> Matt Sicker 
>>
>
>
>
> --
> Cheers,
> Paul
>
>
>


-- 
Cheers,
Paul


Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
Yes, logger.log(MyCustomLEvels.LEVEL1, “message”); works right now.  See the 
ExtendedLevels class in log4j-core test as an example on how to declare the 
level.

I think several of us think that finding a way to make it easy to create 
extended logger methods would be very nice, but I don’t believe it is a 
requirement.

Ralph

On Jan 26, 2014, at 6:46 PM, Paul Benedict  wrote:

> I got lost in the discussion. Can someone please clarify... Is the custom 
> logging interface a nice-to-have or a requirement of the system?
> 
> I was hoping simply someone could write this (pseudocode below):
> logger.log(MyCustomLevels.LEVEL1, "message");
> 
> ...so no different interface should be required, right? Can't someone just 
> pass in their log level directly without using one of the named-log-level 
> convenience methods?
> 
> 
> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
> Now Level can't be used in an annotation. Since it supports string names for 
> levels, should I just use Level.toLevel?
> 
> 
> On 26 January 2014 19:55, Ralph Goers  wrote:
> I think I must be misunderstanding the part about “If those levels were 
> added…”.  I don’t understand how a level can be added to a class from the 
> config such that it is usable by a programmer at compile time.
> 
> Ralph
> 
> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
> 
>> Couldn't we no-op instead of throw if the same identical level were 
>> registered?
>> 
>> If those levels were then added to the same custom level class from the 
>> config, could we use that single class in the logger calls?
>> On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
>> I am certain I could create a LevelPlugin that would allow you to define one 
>> or more Levels in the configuration, but to use that Level the user would 
>> have to code:
>> 
>> logger.log(Level.toLevel(“DIAG”), “hello world”);
>> 
>> In order to directly reference the level it has to be declared as a static 
>> from somewhere and it can only be instantiated a single time, so creating it 
>> from the configuration will prevent that.
>> 
>> Ralph
>> 
>> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
>> 
>>> I have one goal: to remove my request for new built in levels by allowing 
>>> the levels to be defined strictly via configuration. I agree there may be 
>>> some hurdles but that's my goal.
>>> 
>>> I'd like to avoid the requirement that users provide their own level 
>>> implementation or use a different API.
>>> 
>>> Scott
>>> 
>> 
> 
> 
> 
> 
> -- 
> Matt Sicker 
> 
> 
> 
> -- 
> Cheers,
> Paul



Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
There are two separate discussions going on here, so it's easy to get lost. We 
should probably split discussions again.

Discussion 1: The finer details of custom levels. I'm fine with using a static 
factory method and making the constructor private, but I'm not a big fan of the 
name. Just sounds awkward. Unfortunately, I can't come up with anything better.

Discussion 2: A wrapper / extended interface for logging using these custom 
levels. Yes, Paul, users can just do this:

logger.log(MyCustomLevels.LEVEL1, "message");

That is already supported by making Level extensible. However, some on the team 
have expressed a desire to make it even easier. Given hypothetical custom 
levels DIAG and NOTE, the following would be a "nice-to-have" as you call it:

logger.note("message");
logger.diag("message");
etc.

We're discussing options to make this possible. However, it is not a 
requirement to enable custom levels. Custom levels are now already possible.

Any objections to breaking discussion 2 off into another thread?

Nick

On Jan 26, 2014, at 8:46 PM, Paul Benedict wrote:

> I got lost in the discussion. Can someone please clarify... Is the custom 
> logging interface a nice-to-have or a requirement of the system?
> 
> I was hoping simply someone could write this (pseudocode below):
> logger.log(MyCustomLevels.LEVEL1, "message");
> 
> ...so no different interface should be required, right? Can't someone just 
> pass in their log level directly without using one of the named-log-level 
> convenience methods?
> 
> 
> On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:
> Now Level can't be used in an annotation. Since it supports string names for 
> levels, should I just use Level.toLevel?
> 
> 
> On 26 January 2014 19:55, Ralph Goers  wrote:
> I think I must be misunderstanding the part about “If those levels were 
> added…”.  I don’t understand how a level can be added to a class from the 
> config such that it is usable by a programmer at compile time.
> 
> Ralph
> 
> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
> 
>> Couldn't we no-op instead of throw if the same identical level were 
>> registered?
>> 
>> If those levels were then added to the same custom level class from the 
>> config, could we use that single class in the logger calls?
>> On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
>> I am certain I could create a LevelPlugin that would allow you to define one 
>> or more Levels in the configuration, but to use that Level the user would 
>> have to code:
>> 
>> logger.log(Level.toLevel(“DIAG”), “hello world”);
>> 
>> In order to directly reference the level it has to be declared as a static 
>> from somewhere and it can only be instantiated a single time, so creating it 
>> from the configuration will prevent that.
>> 
>> Ralph
>> 
>> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
>> 
>>> I have one goal: to remove my request for new built in levels by allowing 
>>> the levels to be defined strictly via configuration. I agree there may be 
>>> some hurdles but that's my goal.
>>> 
>>> I'd like to avoid the requirement that users provide their own level 
>>> implementation or use a different API.
>>> 
>>> Scott
>>> 
>> 
> 
> 
> 
> 
> -- 
> Matt Sicker 
> 
> 
> 
> -- 
> Cheers,
> Paul



Re: Enums and Custom Levels - completed.

2014-01-26 Thread Paul Benedict
I got lost in the discussion. Can someone please clarify... Is the custom
logging interface a nice-to-have or a requirement of the system?

I was hoping simply someone could write this (pseudocode below):
logger.log(MyCustomLevels.LEVEL1, "message");

...so no different interface should be required, right? Can't someone just
pass in their log level directly without using one of the named-log-level
convenience methods?


On Sun, Jan 26, 2014 at 8:37 PM, Matt Sicker  wrote:

> Now Level can't be used in an annotation. Since it supports string names
> for levels, should I just use Level.toLevel?
>
>
> On 26 January 2014 19:55, Ralph Goers  wrote:
>
>> I think I must be misunderstanding the part about “If those levels were
>> added…”.  I don’t understand how a level can be added to a class from the
>> config such that it is usable by a programmer at compile time.
>>
>> Ralph
>>
>> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
>>
>> Couldn't we no-op instead of throw if the same identical level were
>> registered?
>>
>> If those levels were then added to the same custom level class from the
>> config, could we use that single class in the logger calls?
>>  On Jan 26, 2014 5:15 PM, "Ralph Goers" 
>> wrote:
>>
>>> I am certain I could create a LevelPlugin that would allow you to define
>>> one or more Levels in the configuration, but to use that Level the user
>>> would have to code:
>>>
>>> logger.log(Level.toLevel(“DIAG”), “hello world”);
>>>
>>> In order to directly reference the level it has to be declared as a
>>> static from somewhere and it can only be instantiated a single time, so
>>> creating it from the configuration will prevent that.
>>>
>>> Ralph
>>>
>>> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
>>>
>>> I have one goal: to remove my request for new built in levels by
>>> allowing the levels to be defined strictly via configuration. I agree there
>>> may be some hurdles but that's my goal.
>>>
>>> I'd like to avoid the requirement that users provide their own level
>>> implementation or use a different API.
>>>
>>> Scott
>>>


>>>
>>
>
>
> --
> Matt Sicker 
>



-- 
Cheers,
Paul


Re: Enums and Custom Levels - completed.

2014-01-26 Thread Matt Sicker
Now Level can't be used in an annotation. Since it supports string names
for levels, should I just use Level.toLevel?


On 26 January 2014 19:55, Ralph Goers  wrote:

> I think I must be misunderstanding the part about “If those levels were
> added…”.  I don’t understand how a level can be added to a class from the
> config such that it is usable by a programmer at compile time.
>
> Ralph
>
> On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:
>
> Couldn't we no-op instead of throw if the same identical level were
> registered?
>
> If those levels were then added to the same custom level class from the
> config, could we use that single class in the logger calls?
>  On Jan 26, 2014 5:15 PM, "Ralph Goers" 
> wrote:
>
>> I am certain I could create a LevelPlugin that would allow you to define
>> one or more Levels in the configuration, but to use that Level the user
>> would have to code:
>>
>> logger.log(Level.toLevel(“DIAG”), “hello world”);
>>
>> In order to directly reference the level it has to be declared as a
>> static from somewhere and it can only be instantiated a single time, so
>> creating it from the configuration will prevent that.
>>
>> Ralph
>>
>> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
>>
>> I have one goal: to remove my request for new built in levels by allowing
>> the levels to be defined strictly via configuration. I agree there may be
>> some hurdles but that's my goal.
>>
>> I'd like to avoid the requirement that users provide their own level
>> implementation or use a different API.
>>
>> Scott
>>
>>>
>>>
>>
>


-- 
Matt Sicker 


Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I think I must be misunderstanding the part about “If those levels were 
added…”.  I don’t understand how a level can be added to a class from the 
config such that it is usable by a programmer at compile time.

Ralph

On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:

> Couldn't we no-op instead of throw if the same identical level were 
> registered?
> 
> If those levels were then added to the same custom level class from the 
> config, could we use that single class in the logger calls?
> On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
> I am certain I could create a LevelPlugin that would allow you to define one 
> or more Levels in the configuration, but to use that Level the user would 
> have to code:
> 
> logger.log(Level.toLevel(“DIAG”), “hello world”);
> 
> In order to directly reference the level it has to be declared as a static 
> from somewhere and it can only be instantiated a single time, so creating it 
> from the configuration will prevent that.
> 
> Ralph
> 
> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
> 
>> I have one goal: to remove my request for new built in levels by allowing 
>> the levels to be defined strictly via configuration. I agree there may be 
>> some hurdles but that's my goal.
>> 
>> I'd like to avoid the requirement that users provide their own level 
>> implementation or use a different API.
>> 
>> Scott
>> 
> 



Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
Why would we want that? It is inconsistent with how we currently use Levels and 
I think it could lead to confusion.

What I think should happen is that this Logger wrapper is also where the custom 
level should be declared.

Ralph

On Jan 26, 2014, at 5:32 PM, Nick Williams  
wrote:

> Sorry, I was leaving the method names off because the user can name the 
> methods whatever they want to. They aren't important to the signature as far 
> as Log4j is concerned.
> 
> You /could/ get the level name from the method name, yes. Using an annotation 
> would allow the user to have a constant, perhaps named DIAG, with a different 
> method name, perhaps named `diagnostic`.
> 
> Nick
> 
> On Jan 26, 2014, at 7:25 PM, Ralph Goers wrote:
> 
>> I think I am missing something. 
>> 
>> First, void(Marker, Message) isn’t a valid method signature so I am not sure 
>> what you are really intending. It looks like you specifically did not add 
>> the level to the method name and are planning on getting it from the 
>> annotation?  If so, I don’t see how that works.
>> 
>> Once there is an interface it is easy to generate a wrapper logger that uses 
>> a proxy to implement the methods. If they are named something like void 
>> diag(String msg) then there is no need to annotate them.  
>> 
>> Ralph
>> 
>> On Jan 26, 2014, at 3:51 PM, Nick Williams  
>> 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 getCustomLogger(Class loggerClass)
>>>  T getCustomLogger(Class loggerClass, Class)
>>>  T getCustomLogger(Class loggerClass, Class, 
>>> MessageFactory)
>>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>>  T getCustomLogger(Class loggerClass, Object)
>>>  T getCustomLogger(Class loggerClass, Object, 
>>> MessageFactory)
>>>  T getCustomLogger(Class loggerClass, String)
>>>  T getCustomLogger(Class 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"  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  
 element, with sub-elements like ... 
 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  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  wrote:
 > I haven’t done anything to directly do that. However, custom levels need 
 > to
 > be mapped to the standard 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
Sorry, I was leaving the method names off because the user can name the methods 
whatever they want to. They aren't important to the signature as far as Log4j 
is concerned.

You /could/ get the level name from the method name, yes. Using an annotation 
would allow the user to have a constant, perhaps named DIAG, with a different 
method name, perhaps named `diagnostic`.

Nick

On Jan 26, 2014, at 7:25 PM, Ralph Goers wrote:

> I think I am missing something. 
> 
> First, void(Marker, Message) isn’t a valid method signature so I am not sure 
> what you are really intending. It looks like you specifically did not add the 
> level to the method name and are planning on getting it from the annotation?  
> If so, I don’t see how that works.
> 
> Once there is an interface it is easy to generate a wrapper logger that uses 
> a proxy to implement the methods. If they are named something like void 
> diag(String msg) then there is no need to annotate them.  
> 
> Ralph
> 
> On Jan 26, 2014, at 3:51 PM, Nick Williams  
> 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 getCustomLogger(Class loggerClass)
>>  T getCustomLogger(Class loggerClass, Class)
>>  T getCustomLogger(Class loggerClass, Class, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>  T getCustomLogger(Class loggerClass, Object)
>>  T getCustomLogger(Class loggerClass, Object, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, String)
>>  T getCustomLogger(Class 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"  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  
>>> element, with sub-elements like ... 
>>> 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  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  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  wrote:
>>> >
>>> >> Are these serialization-wise going to be the same as standard levels?
>>> >>
>>> >> Receivers and apps like Chainsaw would benefit from not requiring the
>>

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
We can’t no-op because the user is doing

public static Level NOTE = new Level(“NOTE”, 123){};

Of course, this will generate a new object, not return a preexisting one. The 
only way around this would be to use a Level factory pattern such as 

public static Level NOTE = Level.getOrCreateLevel(“NOTE”, 123);

I actually like that as it means the Level constructor can then be private.

I think it is worth it to make that change.

Ralph

On Jan 26, 2014, at 5:24 PM, Scott Deboy  wrote:

> Couldn't we no-op instead of throw if the same identical level were 
> registered?
> 
> If those levels were then added to the same custom level class from the 
> config, could we use that single class in the logger calls?
> On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:
> I am certain I could create a LevelPlugin that would allow you to define one 
> or more Levels in the configuration, but to use that Level the user would 
> have to code:
> 
> logger.log(Level.toLevel(“DIAG”), “hello world”);
> 
> In order to directly reference the level it has to be declared as a static 
> from somewhere and it can only be instantiated a single time, so creating it 
> from the configuration will prevent that.
> 
> Ralph
> 
> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
> 
>> I have one goal: to remove my request for new built in levels by allowing 
>> the levels to be defined strictly via configuration. I agree there may be 
>> some hurdles but that's my goal.
>> 
>> I'd like to avoid the requirement that users provide their own level 
>> implementation or use a different API.
>> 
>> Scott
>> On Jan 26, 2014 3:52 PM, "Nick Williams"  
>> 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 getCustomLogger(Class loggerClass)
>>  T getCustomLogger(Class loggerClass, Class)
>>  T getCustomLogger(Class loggerClass, Class, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>  T getCustomLogger(Class loggerClass, Object)
>>  T getCustomLogger(Class loggerClass, Object, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, String)
>>  T getCustomLogger(Class 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"  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  
>>> element, with sub-elements like ... 
>>> 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  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 yo

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I think I am missing something. 

First, void(Marker, Message) isn’t a valid method signature so I am not sure 
what you are really intending. It looks like you specifically did not add the 
level to the method name and are planning on getting it from the annotation?  
If so, I don’t see how that works.

Once there is an interface it is easy to generate a wrapper logger that uses a 
proxy to implement the methods. If they are named something like void 
diag(String msg) then there is no need to annotate them.  

Ralph

On Jan 26, 2014, at 3:51 PM, Nick Williams  
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 getCustomLogger(Class loggerClass)
>  T getCustomLogger(Class loggerClass, Class)
>  T getCustomLogger(Class loggerClass, Class, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, MessageFactory)
>  T getCustomLogger(Class loggerClass, Object)
>  T getCustomLogger(Class loggerClass, Object, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, String)
>  T getCustomLogger(Class 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"  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  
>> element, with sub-elements like ... 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  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  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  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"  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" 
>> >> wrote:
>> >> >
>> >> > I have completed the work on custom levels.  It uses a variation of
>> >> > Nick’s “extensible enum” cl

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Scott Deboy
Couldn't we no-op instead of throw if the same identical level were
registered?

If those levels were then added to the same custom level class from the
config, could we use that single class in the logger calls?
 On Jan 26, 2014 5:15 PM, "Ralph Goers"  wrote:

> I am certain I could create a LevelPlugin that would allow you to define
> one or more Levels in the configuration, but to use that Level the user
> would have to code:
>
> logger.log(Level.toLevel("DIAG"), "hello world");
>
> In order to directly reference the level it has to be declared as a static
> from somewhere and it can only be instantiated a single time, so creating
> it from the configuration will prevent that.
>
> Ralph
>
> On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:
>
> I have one goal: to remove my request for new built in levels by allowing
> the levels to be defined strictly via configuration. I agree there may be
> some hurdles but that's my goal.
>
> I'd like to avoid the requirement that users provide their own level
> implementation or use a different API.
>
> Scott
>  On Jan 26, 2014 3:52 PM, "Nick Williams" 
> 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 getCustomLogger(Class loggerClass)
>>  T getCustomLogger(Class loggerClass, Class)
>>  T getCustomLogger(Class loggerClass, Class,
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>  T getCustomLogger(Class loggerClass, Object)
>>  T getCustomLogger(Class loggerClass, Object,
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, String)
>>  T getCustomLogger(Class 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"  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 
>>> element, with sub-elements like ...
>>> 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 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  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 
 wrote:
 >
 >> Are these serialization-wise going to be the same as standard levels?
 >>
 >> Receivers an

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I am certain I could create a LevelPlugin that would allow you to define one or 
more Levels in the configuration, but to use that Level the user would have to 
code:

logger.log(Level.toLevel(“DIAG”), “hello world”);

In order to directly reference the level it has to be declared as a static from 
somewhere and it can only be instantiated a single time, so creating it from 
the configuration will prevent that.

Ralph

On Jan 26, 2014, at 4:03 PM, Scott Deboy  wrote:

> I have one goal: to remove my request for new built in levels by allowing the 
> levels to be defined strictly via configuration. I agree there may be some 
> hurdles but that's my goal.
> 
> I'd like to avoid the requirement that users provide their own level 
> implementation or use a different API.
> 
> Scott
> On Jan 26, 2014 3:52 PM, "Nick Williams"  
> 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 getCustomLogger(Class loggerClass)
>  T getCustomLogger(Class loggerClass, Class)
>  T getCustomLogger(Class loggerClass, Class, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, MessageFactory)
>  T getCustomLogger(Class loggerClass, Object)
>  T getCustomLogger(Class loggerClass, Object, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, String)
>  T getCustomLogger(Class 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"  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  
>> element, with sub-elements like ... 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  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  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  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"  wrote:
>> >> So I assume we could build on this by adding the ability to generate these
>> >> 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Remko Popma
Sorry if I misread. Any mechanism that supports custom levels and gets as
close as possible to the ease of use of the built-in logger interface is
fine with me.

On Monday, January 27, 2014, Gary Gregory  wrote:

> Please read my message again. I talk about wrapping not extending.
>
> Gary
>
>
>  Original message 
> From: Remko Popma
> Date:01/26/2014 18:17 (GMT-05:00)
> To: Log4J Developers List
> Subject: Re: Enums and Custom Levels - completed.
>
> 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 
> element, with sub-elements like ...
> 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 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  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  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"  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" 
> >> 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=“” 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 
> >> > 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 
> >> >> 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 crea
>
>


Re: Enums and Custom Levels - completed.

2014-01-26 Thread Gary Gregory
Please read my message again. I talk about wrapping not extending. 

Gary

 Original message 
From: Remko Popma  
Date:01/26/2014  18:17  (GMT-05:00) 
To: Log4J Developers List  
Subject: Re: Enums and Custom Levels - completed. 

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  element, with 
sub-elements like ... 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  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  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  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"  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" 
>> 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=“” 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 
>> > 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 
>> >> 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 
>> >>> wrote:
>> >>>>
>> >>>> On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma 
>> >>>> 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

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Matt Sicker
If the explicit values of the enum aren't used, then the logger methods
that take a level would still work just fine. That's with the funky  & Level> generic, too, right?


On 26 January 2014 18:14, Ralph Goers  wrote:

> Oh, actually I used an Interface for Level and an enum for the standard
> levels, so I didn’t try what you are suggesting.  I don’t see how what you
> are proposing would work since all the Logger methods take a Level.  If
> Level is an enum then only the values defined in it can be used, regardless
> of whatever interface it might implement.
>
> Ralph
>
> On Jan 26, 2014, at 4:10 PM, Ralph Goers 
> wrote:
>
> 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  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 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 getCustomLogger(Class loggerClass)
>>  T getCustomLogger(Class loggerClass, Class)
>>  T getCustomLogger(Class loggerClass, Class,
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>  T getCustomLogger(Class loggerClass, Object)
>>  T getCustomLogger(Class loggerClass, Object,
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, String)
>>  T getCustomLogger(Class 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"  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 
>>> element, with sub-elements like ...
>>> 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 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  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.
 >

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
Oh, actually I used an Interface for Level and an enum for the standard levels, 
so I didn’t try what you are suggesting.  I don’t see how what you are 
proposing would work since all the Logger methods take a Level.  If Level is an 
enum then only the values defined in it can be used, regardless of whatever 
interface it might implement.

Ralph

On Jan 26, 2014, at 4:10 PM, Ralph Goers  wrote:

> 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  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  
>> 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 getCustomLogger(Class loggerClass)
>>  T getCustomLogger(Class loggerClass, Class)
>>  T getCustomLogger(Class loggerClass, Class, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, MessageFactory)
>>  T getCustomLogger(Class loggerClass, Object)
>>  T getCustomLogger(Class loggerClass, Object, 
>> MessageFactory)
>>  T getCustomLogger(Class loggerClass, String)
>>  T getCustomLogger(Class 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"  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  
>>> element, with sub-elements like ... 
>>> 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  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  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  wrote:
>>> >
>>> >> Are these serialization-wise going to be the same as standard levels?
>>> >>
>>> >> Recei

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
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  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  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 getCustomLogger(Class loggerClass)
>  T getCustomLogger(Class loggerClass, Class)
>  T getCustomLogger(Class loggerClass, Class, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, MessageFactory)
>  T getCustomLogger(Class loggerClass, Object)
>  T getCustomLogger(Class loggerClass, Object, 
> MessageFactory)
>  T getCustomLogger(Class loggerClass, String)
>  T getCustomLogger(Class 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"  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  
>> element, with sub-elements like ... 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  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  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  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"  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" 
>> >> wrote:
>> >> >
>> >> > I h

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I think this is very similar to my most recent commit.  Since you are OK with 
removing the ordinal I am going to do that along with fix the problem Remko 
mentioned.

Ralph

On Jan 26, 2014, at 2:40 PM, Nick Williams  
wrote:

> I would be OK with getting rid of the ordinal. It makes it less enum-like, 
> but I agree that the ordinal really has little purpose now. The intLevel is 
> more important.
> 
> Here may be the best approach I can think of for calculating the 
> StandardLevel-equivalent on instantiation:
> 
>public static Level OFF = new Level("OFF", 0, StandardLevel.OFF) {};
>...
>public static Level ALL = new Level("ALL", Integer.MAX_VALUE, 
> StandardLevel.ALL);
> 
>...
> 
>private Level(String name, int intLevel, StandardLevel standardLevel) { // 
> this is the only c-tor standard levels use
>// same logic as current constructor
>this.standardLevel = standardLevel;
>}
> 
>protected Level(String name, int intLevel) { // this is the only c-tor 
> custom levels use
>this(name, intLevel, Level.calculateStandardLevel(intLevel));
>}
> 
>public enum StandardLevel {
>OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL
>}
> 
> Thoughts?
> 
> N
> 
> On Jan 26, 2014, at 4:02 PM, Ralph Goers wrote:
> 
>> I do have one other comment. You mention that the ordinal value isn’t 
>> guaranteed because the levels might be instantiated in a different order 
>> each time.  An alternative wold be to just get rid of the ordinal.  It isn’t 
>> used anywhere by anything and when custom values are added they will be 
>> added after the standard levels, which is correct but might not be what you 
>> would expect.  Eliminating that would allow the static initialization to 
>> stay as it is and get rid of the need for synchronization in the constructor.
>> 
>> Ralph
>> 
>> On Jan 26, 2014, at 12:41 PM, Nick Williams  
>> wrote:
>> 
>>> Some (ok, a lot of) feedback:
>>> 
>>> - `private static ConcurrentMap levels` should be final.
>>> 
>>> - `private static Object constructorLock` should be final. In fact, code 
>>> inspection flags this as a warning since code synchronizes on it.
>>> 
>>> - The standard Level constants should be instantiated in a static 
>>> initializer like in my original code. Otherwise the order they are 
>>> instantiated in is unpredictable, and DEBUG (for example) may even have a 
>>> different ordinal each time the JVM starts. 
>>> 
>>> - Level isn't abstract. However, you use `new Level("xxx", n) {}` 
>>> (brackets) for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL, 
>>> but you use `new Level("xxx", n)` (no brackets) for other levels. IMO, 
>>> Level should be abstract (so that there's always exactly one instance of 
>>> every class that extends Level, just like a real enum), and the levels 
>>> should all use {} to construct. However, if we don't make Level abstract, 
>>> then we should remove {} from OFF, NOTE, and DETAIL because it's 
>>> unnecessary.
>>> 
>>> - The way StdLevel appears in the middle of Level separates its static 
>>> fields from its instance fields, constructor, and methods. It makes it 
>>> difficult to read. I have to scroll pass StdLevel to see the rest of Level. 
>>> Can we please move StdLevel to the bottom of Level?
>>> 
>>> - This is more personal preference, but I don't like abbreviating things in 
>>> class names. What is Std? We may know, but does everyone? To someone 
>>> unfamiliar with English, Standard is easy to translate, but they have to 
>>> first figure out that Std is short for Std. Can be please un-abbreviate 
>>> this to StandardLevel?
>>> 
>>> - I disagree with this approach:
>>> 
>>>  if (levels.containsKey(name)) {
>>>  Level level = levels.get(name);
>>>  if (level.intLevel() != intLevel) {
>>>  throw new IllegalArgumentException("Level " + name + " has 
>>> already been defined.");
>>>  }
>>>  ordinal = level.ordinal;
>>>  }
>>> 
>>> This allows multiple Levels with the same name/intLevel to be instantiated, 
>>> which prevents equality testing (level == Level.OFF) from being 100% 
>>> deterministic. It should really be this:
>>> 
>>>  if (levels.containsKey(name)) {
>>>  throw new IllegalArgumentException("Level " + name + " has 
>>> already been defined.");
>>>  }
>>> 
>>> - I think we should make all of the methods of Level final. Custom levels 
>>> shouldn't be able to change their behavior, IMO. Alternatively, if we don't 
>>> make Level abstract, we should make it final.
>>> 
>>> - Level has no JavaDoc. The Level constants in Level have no JavaDoc. That 
>>> needs to be fixed.
>>> 
>>> - I'm still not convinced StdLevel/StandardLevel is necessary. It seems 
>>> like an anti-pattern to me. From what I can tell (please let me know if I'm 
>>> missing something), StdLevel's entire purpose is to allow us to still 
>>> switch on the standard levels. I think that's

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Scott Deboy
I have one goal: to remove my request for new built in levels by allowing
the levels to be defined strictly via configuration. I agree there may be
some hurdles but that's my goal.

I'd like to avoid the requirement that users provide their own level
implementation or use a different API.

Scott
 On Jan 26, 2014 3:52 PM, "Nick Williams" 
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 getCustomLogger(Class loggerClass)
>  T getCustomLogger(Class loggerClass, Class)
>  T getCustomLogger(Class loggerClass, Class,
> MessageFactory)
>  T getCustomLogger(Class loggerClass, MessageFactory)
>  T getCustomLogger(Class loggerClass, Object)
>  T getCustomLogger(Class loggerClass, Object,
> MessageFactory)
>  T getCustomLogger(Class loggerClass, String)
>  T getCustomLogger(Class 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"  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 
>> element, with sub-elements like ...
>> 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 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  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 
>>> 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"  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" 
>>> >> 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=“” category=“Level”) for them to be usable
>>> during
>>> >> >

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Matt Sicker
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 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 getCustomLogger(Class loggerClass)
>  T getCustomLogger(Class loggerClass, Class)
>  T getCustomLogger(Class loggerClass, Class,
> MessageFactory)
>  T getCustomLogger(Class loggerClass, MessageFactory)
>  T getCustomLogger(Class loggerClass, Object)
>  T getCustomLogger(Class loggerClass, Object,
> MessageFactory)
>  T getCustomLogger(Class loggerClass, String)
>  T getCustomLogger(Class 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"  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 
>> element, with sub-elements like ...
>> 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 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  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 
>>> 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"  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" 
>>> >> 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

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
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 getCustomLogger(Class loggerClass)
 T getCustomLogger(Class loggerClass, Class)
 T getCustomLogger(Class loggerClass, Class, 
MessageFactory)
 T getCustomLogger(Class loggerClass, MessageFactory)
 T getCustomLogger(Class loggerClass, Object)
 T getCustomLogger(Class loggerClass, Object, 
MessageFactory)
 T getCustomLogger(Class loggerClass, String)
 T getCustomLogger(Class 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"  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  
> element, with sub-elements like ... 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  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  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  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"  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" 
> >> 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=“” 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 
> >> > 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 
> >> >> wrote:
> >> >>
> >> >>> What is the best way to make progress on the custom 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Scott Deboy
Yes that's what I was thinking.

Scott
On Jan 26, 2014 3:18 PM, "Remko Popma"  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 
> element, with sub-elements like ...
> 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 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  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  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"  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" 
>> >> 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="" 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 > >
>> >> > 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 
>> >> >> 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 <
>> garydgreg...@gmail.com>
>> >> >>> wrote:
>> >> 
>> >>  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 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
I agree. The circumstance that could cause a problem here would be rare, but 
not impossible. We should use Remko's code here.

Nick

On Jan 26, 2014, at 5:20 PM, Remko Popma wrote:

> By the way, there may be a small concurrency bug in the Level.values() static 
> method. This may be better:
> 
> public static Level[] values() {
> Collection values = Level.levels.values();
> return values.toArray(new Level[values.size()]); // use value 
> collection size, not map size
> }
> 
> 
> 
> On Mon, Jan 27, 2014 at 7:43 AM, Matt Sicker  wrote:
> +1 to everything Nick said.
> 
> 
> On 26 January 2014 16:40, Nick Williams  wrote:
> I would be OK with getting rid of the ordinal. It makes it less enum-like, 
> but I agree that the ordinal really has little purpose now. The intLevel is 
> more important.
> 
> Here may be the best approach I can think of for calculating the 
> StandardLevel-equivalent on instantiation:
> 
> public static Level OFF = new Level("OFF", 0, StandardLevel.OFF) {};
> ...
> public static Level ALL = new Level("ALL", Integer.MAX_VALUE, 
> StandardLevel.ALL);
> 
> ...
> 
> private Level(String name, int intLevel, StandardLevel standardLevel) { 
> // this is the only c-tor standard levels use
> // same logic as current constructor
> this.standardLevel = standardLevel;
> }
> 
> protected Level(String name, int intLevel) { // this is the only c-tor 
> custom levels use
> this(name, intLevel, Level.calculateStandardLevel(intLevel));
> }
> 
> public enum StandardLevel {
> OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL
> }
> 
> Thoughts?
> 
> N
> 
> On Jan 26, 2014, at 4:02 PM, Ralph Goers wrote:
> 
> > I do have one other comment. You mention that the ordinal value isn’t 
> > guaranteed because the levels might be instantiated in a different order 
> > each time.  An alternative wold be to just get rid of the ordinal.  It 
> > isn’t used anywhere by anything and when custom values are added they will 
> > be added after the standard levels, which is correct but might not be what 
> > you would expect.  Eliminating that would allow the static initialization 
> > to stay as it is and get rid of the need for synchronization in the 
> > constructor.
> >
> > Ralph
> >
> > On Jan 26, 2014, at 12:41 PM, Nick Williams  
> > wrote:
> >
> >> Some (ok, a lot of) feedback:
> >>
> >> - `private static ConcurrentMap levels` should be final.
> >>
> >> - `private static Object constructorLock` should be final. In fact, code 
> >> inspection flags this as a warning since code synchronizes on it.
> >>
> >> - The standard Level constants should be instantiated in a static 
> >> initializer like in my original code. Otherwise the order they are 
> >> instantiated in is unpredictable, and DEBUG (for example) may even have a 
> >> different ordinal each time the JVM starts.
> >>
> >> - Level isn't abstract. However, you use `new Level("xxx", n) {}` 
> >> (brackets) for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL, 
> >> but you use `new Level("xxx", n)` (no brackets) for other levels. IMO, 
> >> Level should be abstract (so that there's always exactly one instance of 
> >> every class that extends Level, just like a real enum), and the levels 
> >> should all use {} to construct. However, if we don't make Level abstract, 
> >> then we should remove {} from OFF, NOTE, and DETAIL because it's 
> >> unnecessary.
> >>
> >> - The way StdLevel appears in the middle of Level separates its static 
> >> fields from its instance fields, constructor, and methods. It makes it 
> >> difficult to read. I have to scroll pass StdLevel to see the rest of 
> >> Level. Can we please move StdLevel to the bottom of Level?
> >>
> >> - This is more personal preference, but I don't like abbreviating things 
> >> in class names. What is Std? We may know, but does everyone? To someone 
> >> unfamiliar with English, Standard is easy to translate, but they have to 
> >> first figure out that Std is short for Std. Can be please un-abbreviate 
> >> this to StandardLevel?
> >>
> >> - I disagree with this approach:
> >>
> >>   if (levels.containsKey(name)) {
> >>   Level level = levels.get(name);
> >>   if (level.intLevel() != intLevel) {
> >>   throw new IllegalArgumentException("Level " + name + " 
> >> has already been defined.");
> >>   }
> >>   ordinal = level.ordinal;
> >>   }
> >>
> >> This allows multiple Levels with the same name/intLevel to be 
> >> instantiated, which prevents equality testing (level == Level.OFF) from 
> >> being 100% deterministic. It should really be this:
> >>
> >>   if (levels.containsKey(name)) {
> >>   throw new IllegalArgumentException("Level " + name + " has 
> >> already been defined.");
> >>   }
> >>
> >> - I think we should make all of the methods of Level final. Custom levels 
> >> shouldn't be able

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Remko Popma
By the way, there may be a small concurrency bug in the Level.values()
static method. This may be better:

public static Level[] values() {
Collection values = Level.levels.values();
return values.toArray(new Level[values.size()]); // use value
collection size, not map size
}



On Mon, Jan 27, 2014 at 7:43 AM, Matt Sicker  wrote:

> +1 to everything Nick said.
>
>
> On 26 January 2014 16:40, Nick Williams wrote:
>
>> I would be OK with getting rid of the ordinal. It makes it less
>> enum-like, but I agree that the ordinal really has little purpose now. The
>> intLevel is more important.
>>
>> Here may be the best approach I can think of for calculating the
>> StandardLevel-equivalent on instantiation:
>>
>> public static Level OFF = new Level("OFF", 0, StandardLevel.OFF) {};
>> ...
>> public static Level ALL = new Level("ALL", Integer.MAX_VALUE,
>> StandardLevel.ALL);
>>
>> ...
>>
>> private Level(String name, int intLevel, StandardLevel standardLevel)
>> { // this is the only c-tor standard levels use
>> // same logic as current constructor
>> this.standardLevel = standardLevel;
>> }
>>
>> protected Level(String name, int intLevel) { // this is the only
>> c-tor custom levels use
>> this(name, intLevel, Level.calculateStandardLevel(intLevel));
>> }
>>
>> public enum StandardLevel {
>> OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL
>> }
>>
>> Thoughts?
>>
>> N
>>
>> On Jan 26, 2014, at 4:02 PM, Ralph Goers wrote:
>>
>> > I do have one other comment. You mention that the ordinal value isn’t
>> guaranteed because the levels might be instantiated in a different order
>> each time.  An alternative wold be to just get rid of the ordinal.  It
>> isn’t used anywhere by anything and when custom values are added they will
>> be added after the standard levels, which is correct but might not be what
>> you would expect.  Eliminating that would allow the static initialization
>> to stay as it is and get rid of the need for synchronization in the
>> constructor.
>> >
>> > Ralph
>> >
>> > On Jan 26, 2014, at 12:41 PM, Nick Williams <
>> nicho...@nicholaswilliams.net> wrote:
>> >
>> >> Some (ok, a lot of) feedback:
>> >>
>> >> - `private static ConcurrentMap levels` should be final.
>> >>
>> >> - `private static Object constructorLock` should be final. In fact,
>> code inspection flags this as a warning since code synchronizes on it.
>> >>
>> >> - The standard Level constants should be instantiated in a static
>> initializer like in my original code. Otherwise the order they are
>> instantiated in is unpredictable, and DEBUG (for example) may even have a
>> different ordinal each time the JVM starts.
>> >>
>> >> - Level isn't abstract. However, you use `new Level("xxx", n) {}`
>> (brackets) for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL,
>> but you use `new Level("xxx", n)` (no brackets) for other levels. IMO,
>> Level should be abstract (so that there's always exactly one instance of
>> every class that extends Level, just like a real enum), and the levels
>> should all use {} to construct. However, if we don't make Level abstract,
>> then we should remove {} from OFF, NOTE, and DETAIL because it's
>> unnecessary.
>> >>
>> >> - The way StdLevel appears in the middle of Level separates its static
>> fields from its instance fields, constructor, and methods. It makes it
>> difficult to read. I have to scroll pass StdLevel to see the rest of Level.
>> Can we please move StdLevel to the bottom of Level?
>> >>
>> >> - This is more personal preference, but I don't like abbreviating
>> things in class names. What is Std? We may know, but does everyone? To
>> someone unfamiliar with English, Standard is easy to translate, but they
>> have to first figure out that Std is short for Std. Can be please
>> un-abbreviate this to StandardLevel?
>> >>
>> >> - I disagree with this approach:
>> >>
>> >>   if (levels.containsKey(name)) {
>> >>   Level level = levels.get(name);
>> >>   if (level.intLevel() != intLevel) {
>> >>   throw new IllegalArgumentException("Level " + name +
>> " has already been defined.");
>> >>   }
>> >>   ordinal = level.ordinal;
>> >>   }
>> >>
>> >> This allows multiple Levels with the same name/intLevel to be
>> instantiated, which prevents equality testing (level == Level.OFF) from
>> being 100% deterministic. It should really be this:
>> >>
>> >>   if (levels.containsKey(name)) {
>> >>   throw new IllegalArgumentException("Level " + name + "
>> has already been defined.");
>> >>   }
>> >>
>> >> - I think we should make all of the methods of Level final. Custom
>> levels shouldn't be able to change their behavior, IMO. Alternatively, if
>> we don't make Level abstract, we should make it final.
>> >>
>> >> - Level has no JavaDoc. The Level constants in Level have no JavaDoc.
>> That needs to

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Remko Popma
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 
element, with sub-elements like ...
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  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  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  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"  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" 
> >> 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=“” 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 
> >> > 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 
> >> >> 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  >
> >> >>> wrote:
> >> 
> >>  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 ar

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Matt Sicker
+1 to everything Nick said.


On 26 January 2014 16:40, Nick Williams wrote:

> I would be OK with getting rid of the ordinal. It makes it less enum-like,
> but I agree that the ordinal really has little purpose now. The intLevel is
> more important.
>
> Here may be the best approach I can think of for calculating the
> StandardLevel-equivalent on instantiation:
>
> public static Level OFF = new Level("OFF", 0, StandardLevel.OFF) {};
> ...
> public static Level ALL = new Level("ALL", Integer.MAX_VALUE,
> StandardLevel.ALL);
>
> ...
>
> private Level(String name, int intLevel, StandardLevel standardLevel)
> { // this is the only c-tor standard levels use
> // same logic as current constructor
> this.standardLevel = standardLevel;
> }
>
> protected Level(String name, int intLevel) { // this is the only c-tor
> custom levels use
> this(name, intLevel, Level.calculateStandardLevel(intLevel));
> }
>
> public enum StandardLevel {
> OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL
> }
>
> Thoughts?
>
> N
>
> On Jan 26, 2014, at 4:02 PM, Ralph Goers wrote:
>
> > I do have one other comment. You mention that the ordinal value isn’t
> guaranteed because the levels might be instantiated in a different order
> each time.  An alternative wold be to just get rid of the ordinal.  It
> isn’t used anywhere by anything and when custom values are added they will
> be added after the standard levels, which is correct but might not be what
> you would expect.  Eliminating that would allow the static initialization
> to stay as it is and get rid of the need for synchronization in the
> constructor.
> >
> > Ralph
> >
> > On Jan 26, 2014, at 12:41 PM, Nick Williams <
> nicho...@nicholaswilliams.net> wrote:
> >
> >> Some (ok, a lot of) feedback:
> >>
> >> - `private static ConcurrentMap levels` should be final.
> >>
> >> - `private static Object constructorLock` should be final. In fact,
> code inspection flags this as a warning since code synchronizes on it.
> >>
> >> - The standard Level constants should be instantiated in a static
> initializer like in my original code. Otherwise the order they are
> instantiated in is unpredictable, and DEBUG (for example) may even have a
> different ordinal each time the JVM starts.
> >>
> >> - Level isn't abstract. However, you use `new Level("xxx", n) {}`
> (brackets) for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL,
> but you use `new Level("xxx", n)` (no brackets) for other levels. IMO,
> Level should be abstract (so that there's always exactly one instance of
> every class that extends Level, just like a real enum), and the levels
> should all use {} to construct. However, if we don't make Level abstract,
> then we should remove {} from OFF, NOTE, and DETAIL because it's
> unnecessary.
> >>
> >> - The way StdLevel appears in the middle of Level separates its static
> fields from its instance fields, constructor, and methods. It makes it
> difficult to read. I have to scroll pass StdLevel to see the rest of Level.
> Can we please move StdLevel to the bottom of Level?
> >>
> >> - This is more personal preference, but I don't like abbreviating
> things in class names. What is Std? We may know, but does everyone? To
> someone unfamiliar with English, Standard is easy to translate, but they
> have to first figure out that Std is short for Std. Can be please
> un-abbreviate this to StandardLevel?
> >>
> >> - I disagree with this approach:
> >>
> >>   if (levels.containsKey(name)) {
> >>   Level level = levels.get(name);
> >>   if (level.intLevel() != intLevel) {
> >>   throw new IllegalArgumentException("Level " + name +
> " has already been defined.");
> >>   }
> >>   ordinal = level.ordinal;
> >>   }
> >>
> >> This allows multiple Levels with the same name/intLevel to be
> instantiated, which prevents equality testing (level == Level.OFF) from
> being 100% deterministic. It should really be this:
> >>
> >>   if (levels.containsKey(name)) {
> >>   throw new IllegalArgumentException("Level " + name + "
> has already been defined.");
> >>   }
> >>
> >> - I think we should make all of the methods of Level final. Custom
> levels shouldn't be able to change their behavior, IMO. Alternatively, if
> we don't make Level abstract, we should make it final.
> >>
> >> - Level has no JavaDoc. The Level constants in Level have no JavaDoc.
> That needs to be fixed.
> >>
> >> - I'm still not convinced StdLevel/StandardLevel is necessary. It seems
> like an anti-pattern to me. From what I can tell (please let me know if I'm
> missing something), StdLevel's entire purpose is to allow us to still
> switch on the standard levels. I think that's a bad reason to create an
> enum whose constants mirror Level. The primary problem with the StdLevel is
> that the conversion from a Level to a StdLevel in many cases happens __on
>

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
I would be OK with getting rid of the ordinal. It makes it less enum-like, but 
I agree that the ordinal really has little purpose now. The intLevel is more 
important.

Here may be the best approach I can think of for calculating the 
StandardLevel-equivalent on instantiation:

public static Level OFF = new Level("OFF", 0, StandardLevel.OFF) {};
...
public static Level ALL = new Level("ALL", Integer.MAX_VALUE, 
StandardLevel.ALL);

...

private Level(String name, int intLevel, StandardLevel standardLevel) { // 
this is the only c-tor standard levels use
// same logic as current constructor
this.standardLevel = standardLevel;
}

protected Level(String name, int intLevel) { // this is the only c-tor 
custom levels use
this(name, intLevel, Level.calculateStandardLevel(intLevel));
}

public enum StandardLevel {
OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL
}

Thoughts?

N

On Jan 26, 2014, at 4:02 PM, Ralph Goers wrote:

> I do have one other comment. You mention that the ordinal value isn’t 
> guaranteed because the levels might be instantiated in a different order each 
> time.  An alternative wold be to just get rid of the ordinal.  It isn’t used 
> anywhere by anything and when custom values are added they will be added 
> after the standard levels, which is correct but might not be what you would 
> expect.  Eliminating that would allow the static initialization to stay as it 
> is and get rid of the need for synchronization in the constructor.
> 
> Ralph
> 
> On Jan 26, 2014, at 12:41 PM, Nick Williams  
> wrote:
> 
>> Some (ok, a lot of) feedback:
>> 
>> - `private static ConcurrentMap levels` should be final.
>> 
>> - `private static Object constructorLock` should be final. In fact, code 
>> inspection flags this as a warning since code synchronizes on it.
>> 
>> - The standard Level constants should be instantiated in a static 
>> initializer like in my original code. Otherwise the order they are 
>> instantiated in is unpredictable, and DEBUG (for example) may even have a 
>> different ordinal each time the JVM starts. 
>> 
>> - Level isn't abstract. However, you use `new Level("xxx", n) {}` (brackets) 
>> for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL, but you use 
>> `new Level("xxx", n)` (no brackets) for other levels. IMO, Level should be 
>> abstract (so that there's always exactly one instance of every class that 
>> extends Level, just like a real enum), and the levels should all use {} to 
>> construct. However, if we don't make Level abstract, then we should remove 
>> {} from OFF, NOTE, and DETAIL because it's unnecessary.
>> 
>> - The way StdLevel appears in the middle of Level separates its static 
>> fields from its instance fields, constructor, and methods. It makes it 
>> difficult to read. I have to scroll pass StdLevel to see the rest of Level. 
>> Can we please move StdLevel to the bottom of Level?
>> 
>> - This is more personal preference, but I don't like abbreviating things in 
>> class names. What is Std? We may know, but does everyone? To someone 
>> unfamiliar with English, Standard is easy to translate, but they have to 
>> first figure out that Std is short for Std. Can be please un-abbreviate this 
>> to StandardLevel?
>> 
>> - I disagree with this approach:
>> 
>>   if (levels.containsKey(name)) {
>>   Level level = levels.get(name);
>>   if (level.intLevel() != intLevel) {
>>   throw new IllegalArgumentException("Level " + name + " has 
>> already been defined.");
>>   }
>>   ordinal = level.ordinal;
>>   }
>> 
>> This allows multiple Levels with the same name/intLevel to be instantiated, 
>> which prevents equality testing (level == Level.OFF) from being 100% 
>> deterministic. It should really be this:
>> 
>>   if (levels.containsKey(name)) {
>>   throw new IllegalArgumentException("Level " + name + " has 
>> already been defined.");
>>   }
>> 
>> - I think we should make all of the methods of Level final. Custom levels 
>> shouldn't be able to change their behavior, IMO. Alternatively, if we don't 
>> make Level abstract, we should make it final.
>> 
>> - Level has no JavaDoc. The Level constants in Level have no JavaDoc. That 
>> needs to be fixed.
>> 
>> - I'm still not convinced StdLevel/StandardLevel is necessary. It seems like 
>> an anti-pattern to me. From what I can tell (please let me know if I'm 
>> missing something), StdLevel's entire purpose is to allow us to still switch 
>> on the standard levels. I think that's a bad reason to create an enum whose 
>> constants mirror Level. The primary problem with the StdLevel is that the 
>> conversion from a Level to a StdLevel in many cases happens __on every 
>> logging event__. That's going to be hugely inefficient. Really, when a 
>> custom Level is created, it should be created with an equivalent standard 
>> Level 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I made most of the changes.

I moved StandardLevel to a separate file in the spi sub-package. The actual 
level values are defined there and then referenced in Level.  This way each 
Level can be associated with a StandardLevel in its constructor.

Ralph

On Jan 26, 2014, at 1:40 PM, Ralph Goers  wrote:

> I agree with most of this and will make the suggested changes.  At least up 
> to the point of getting rid of the StandardLevel enum. That is used in too 
> many places to map to some other framework. I agree that doing the 
> calculation every time is not the right way to go and will see what I can do, 
> but I don’t like passing the standard level as a parameter - it should be 
> based solely on the intValue.  However, that would mean the StandardLevel 
> enum has to be created before the Levels themselves are created.
> 
> Ralph
> 
> On Jan 26, 2014, at 12:41 PM, Nick Williams  
> wrote:
> 
>> Some (ok, a lot of) feedback:
>> 
>> - `private static ConcurrentMap levels` should be final.
>> 
>> - `private static Object constructorLock` should be final. In fact, code 
>> inspection flags this as a warning since code synchronizes on it.
>> 
>> - The standard Level constants should be instantiated in a static 
>> initializer like in my original code. Otherwise the order they are 
>> instantiated in is unpredictable, and DEBUG (for example) may even have a 
>> different ordinal each time the JVM starts. 
>> 
>> - Level isn't abstract. However, you use `new Level("xxx", n) {}` (brackets) 
>> for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL, but you use 
>> `new Level("xxx", n)` (no brackets) for other levels. IMO, Level should be 
>> abstract (so that there's always exactly one instance of every class that 
>> extends Level, just like a real enum), and the levels should all use {} to 
>> construct. However, if we don't make Level abstract, then we should remove 
>> {} from OFF, NOTE, and DETAIL because it's unnecessary.
>> 
>> - The way StdLevel appears in the middle of Level separates its static 
>> fields from its instance fields, constructor, and methods. It makes it 
>> difficult to read. I have to scroll pass StdLevel to see the rest of Level. 
>> Can we please move StdLevel to the bottom of Level?
>> 
>> - This is more personal preference, but I don't like abbreviating things in 
>> class names. What is Std? We may know, but does everyone? To someone 
>> unfamiliar with English, Standard is easy to translate, but they have to 
>> first figure out that Std is short for Std. Can be please un-abbreviate this 
>> to StandardLevel?
>> 
>> - I disagree with this approach:
>> 
>>   if (levels.containsKey(name)) {
>>   Level level = levels.get(name);
>>   if (level.intLevel() != intLevel) {
>>   throw new IllegalArgumentException("Level " + name + " has 
>> already been defined.");
>>   }
>>   ordinal = level.ordinal;
>>   }
>> 
>> This allows multiple Levels with the same name/intLevel to be instantiated, 
>> which prevents equality testing (level == Level.OFF) from being 100% 
>> deterministic. It should really be this:
>> 
>>   if (levels.containsKey(name)) {
>>   throw new IllegalArgumentException("Level " + name + " has 
>> already been defined.");
>>   }
>> 
>> - I think we should make all of the methods of Level final. Custom levels 
>> shouldn't be able to change their behavior, IMO. Alternatively, if we don't 
>> make Level abstract, we should make it final.
>> 
>> - Level has no JavaDoc. The Level constants in Level have no JavaDoc. That 
>> needs to be fixed.
>> 
>> - I'm still not convinced StdLevel/StandardLevel is necessary. It seems like 
>> an anti-pattern to me. From what I can tell (please let me know if I'm 
>> missing something), StdLevel's entire purpose is to allow us to still switch 
>> on the standard levels. I think that's a bad reason to create an enum whose 
>> constants mirror Level. The primary problem with the StdLevel is that the 
>> conversion from a Level to a StdLevel in many cases happens __on every 
>> logging event__. That's going to be hugely inefficient. Really, when a 
>> custom Level is created, it should be created with an equivalent standard 
>> Level (or StdLevel). There are several ways to accomplish this that are open 
>> to discussion, but I don't think the current StdLevel.getStdLevel is the 
>> right approach. One alternative:
>> 
>>   private final Level standardLevel;
>> 
>>   protected Level(String name, int level, Level mapToOtherFrameworksAs) {
>>   this(name, level);
>>   this.standardLevel = mapToOtherFrameworksAs;
>>   }
>> 
>>   private Level(String name, int level) {
>>   // same as now
>>   this.standardLevel = this;
>>   }
>> 
>>   public final Level getStandardLevel() {
>>   return this.standardLevel;
>>   }
>> 
>> This does, admittedly, have some problems. Another alternative that I could 
>> also be happy wit

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I do have one other comment. You mention that the ordinal value isn’t 
guaranteed because the levels might be instantiated in a different order each 
time.  An alternative wold be to just get rid of the ordinal.  It isn’t used 
anywhere by anything and when custom values are added they will be added after 
the standard levels, which is correct but might not be what you would expect.  
Eliminating that would allow the static initialization to stay as it is and get 
rid of the need for synchronization in the constructor.

Ralph

On Jan 26, 2014, at 12:41 PM, Nick Williams  
wrote:

> Some (ok, a lot of) feedback:
> 
> - `private static ConcurrentMap levels` should be final.
> 
> - `private static Object constructorLock` should be final. In fact, code 
> inspection flags this as a warning since code synchronizes on it.
> 
> - The standard Level constants should be instantiated in a static initializer 
> like in my original code. Otherwise the order they are instantiated in is 
> unpredictable, and DEBUG (for example) may even have a different ordinal each 
> time the JVM starts. 
> 
> - Level isn't abstract. However, you use `new Level("xxx", n) {}` (brackets) 
> for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL, but you use 
> `new Level("xxx", n)` (no brackets) for other levels. IMO, Level should be 
> abstract (so that there's always exactly one instance of every class that 
> extends Level, just like a real enum), and the levels should all use {} to 
> construct. However, if we don't make Level abstract, then we should remove {} 
> from OFF, NOTE, and DETAIL because it's unnecessary.
> 
> - The way StdLevel appears in the middle of Level separates its static fields 
> from its instance fields, constructor, and methods. It makes it difficult to 
> read. I have to scroll pass StdLevel to see the rest of Level. Can we please 
> move StdLevel to the bottom of Level?
> 
> - This is more personal preference, but I don't like abbreviating things in 
> class names. What is Std? We may know, but does everyone? To someone 
> unfamiliar with English, Standard is easy to translate, but they have to 
> first figure out that Std is short for Std. Can be please un-abbreviate this 
> to StandardLevel?
> 
> - I disagree with this approach:
> 
>if (levels.containsKey(name)) {
>Level level = levels.get(name);
>if (level.intLevel() != intLevel) {
>throw new IllegalArgumentException("Level " + name + " has 
> already been defined.");
>}
>ordinal = level.ordinal;
>}
> 
>  This allows multiple Levels with the same name/intLevel to be instantiated, 
> which prevents equality testing (level == Level.OFF) from being 100% 
> deterministic. It should really be this:
> 
>if (levels.containsKey(name)) {
>throw new IllegalArgumentException("Level " + name + " has 
> already been defined.");
>}
> 
> - I think we should make all of the methods of Level final. Custom levels 
> shouldn't be able to change their behavior, IMO. Alternatively, if we don't 
> make Level abstract, we should make it final.
> 
> - Level has no JavaDoc. The Level constants in Level have no JavaDoc. That 
> needs to be fixed.
> 
> - I'm still not convinced StdLevel/StandardLevel is necessary. It seems like 
> an anti-pattern to me. From what I can tell (please let me know if I'm 
> missing something), StdLevel's entire purpose is to allow us to still switch 
> on the standard levels. I think that's a bad reason to create an enum whose 
> constants mirror Level. The primary problem with the StdLevel is that the 
> conversion from a Level to a StdLevel in many cases happens __on every 
> logging event__. That's going to be hugely inefficient. Really, when a custom 
> Level is created, it should be created with an equivalent standard Level (or 
> StdLevel). There are several ways to accomplish this that are open to 
> discussion, but I don't think the current StdLevel.getStdLevel is the right 
> approach. One alternative:
> 
>private final Level standardLevel;
> 
>protected Level(String name, int level, Level mapToOtherFrameworksAs) {
>this(name, level);
>this.standardLevel = mapToOtherFrameworksAs;
>}
> 
>private Level(String name, int level) {
>// same as now
>this.standardLevel = this;
>}
> 
>public final Level getStandardLevel() {
>return this.standardLevel;
>}
> 
> This does, admittedly, have some problems. Another alternative that I could 
> also be happy with that keeps the StandardLevel enum:
> 
>private final StandardLevel standardLevel;
> 
>protected Level(String name, int level, StandardLevel 
> mapToOtherFrameworksAs) {
>this(name, level);
>this.standardLevel = mapToOtherFrameworksAs;
>}
> 
>private Level(String name, int level) {
>// same as now
>this.standardLevel = this;
>}
> 
>

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I agree with most of this and will make the suggested changes.  At least up to 
the point of getting rid of the StandardLevel enum. That is used in too many 
places to map to some other framework. I agree that doing the calculation every 
time is not the right way to go and will see what I can do, but I don’t like 
passing the standard level as a parameter - it should be based solely on the 
intValue.  However, that would mean the StandardLevel enum has to be created 
before the Levels themselves are created.

Ralph

On Jan 26, 2014, at 12:41 PM, Nick Williams  
wrote:

> Some (ok, a lot of) feedback:
> 
> - `private static ConcurrentMap levels` should be final.
> 
> - `private static Object constructorLock` should be final. In fact, code 
> inspection flags this as a warning since code synchronizes on it.
> 
> - The standard Level constants should be instantiated in a static initializer 
> like in my original code. Otherwise the order they are instantiated in is 
> unpredictable, and DEBUG (for example) may even have a different ordinal each 
> time the JVM starts. 
> 
> - Level isn't abstract. However, you use `new Level("xxx", n) {}` (brackets) 
> for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL, but you use 
> `new Level("xxx", n)` (no brackets) for other levels. IMO, Level should be 
> abstract (so that there's always exactly one instance of every class that 
> extends Level, just like a real enum), and the levels should all use {} to 
> construct. However, if we don't make Level abstract, then we should remove {} 
> from OFF, NOTE, and DETAIL because it's unnecessary.
> 
> - The way StdLevel appears in the middle of Level separates its static fields 
> from its instance fields, constructor, and methods. It makes it difficult to 
> read. I have to scroll pass StdLevel to see the rest of Level. Can we please 
> move StdLevel to the bottom of Level?
> 
> - This is more personal preference, but I don't like abbreviating things in 
> class names. What is Std? We may know, but does everyone? To someone 
> unfamiliar with English, Standard is easy to translate, but they have to 
> first figure out that Std is short for Std. Can be please un-abbreviate this 
> to StandardLevel?
> 
> - I disagree with this approach:
> 
>if (levels.containsKey(name)) {
>Level level = levels.get(name);
>if (level.intLevel() != intLevel) {
>throw new IllegalArgumentException("Level " + name + " has 
> already been defined.");
>}
>ordinal = level.ordinal;
>}
> 
>  This allows multiple Levels with the same name/intLevel to be instantiated, 
> which prevents equality testing (level == Level.OFF) from being 100% 
> deterministic. It should really be this:
> 
>if (levels.containsKey(name)) {
>throw new IllegalArgumentException("Level " + name + " has 
> already been defined.");
>}
> 
> - I think we should make all of the methods of Level final. Custom levels 
> shouldn't be able to change their behavior, IMO. Alternatively, if we don't 
> make Level abstract, we should make it final.
> 
> - Level has no JavaDoc. The Level constants in Level have no JavaDoc. That 
> needs to be fixed.
> 
> - I'm still not convinced StdLevel/StandardLevel is necessary. It seems like 
> an anti-pattern to me. From what I can tell (please let me know if I'm 
> missing something), StdLevel's entire purpose is to allow us to still switch 
> on the standard levels. I think that's a bad reason to create an enum whose 
> constants mirror Level. The primary problem with the StdLevel is that the 
> conversion from a Level to a StdLevel in many cases happens __on every 
> logging event__. That's going to be hugely inefficient. Really, when a custom 
> Level is created, it should be created with an equivalent standard Level (or 
> StdLevel). There are several ways to accomplish this that are open to 
> discussion, but I don't think the current StdLevel.getStdLevel is the right 
> approach. One alternative:
> 
>private final Level standardLevel;
> 
>protected Level(String name, int level, Level mapToOtherFrameworksAs) {
>this(name, level);
>this.standardLevel = mapToOtherFrameworksAs;
>}
> 
>private Level(String name, int level) {
>// same as now
>this.standardLevel = this;
>}
> 
>public final Level getStandardLevel() {
>return this.standardLevel;
>}
> 
> This does, admittedly, have some problems. Another alternative that I could 
> also be happy with that keeps the StandardLevel enum:
> 
>private final StandardLevel standardLevel;
> 
>protected Level(String name, int level, StandardLevel 
> mapToOtherFrameworksAs) {
>this(name, level);
>this.standardLevel = mapToOtherFrameworksAs;
>}
> 
>private Level(String name, int level) {
>// same as now
>this.standardLevel = this;
>}
> 
>public

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
Some (ok, a lot of) feedback:

- `private static ConcurrentMap levels` should be final.

- `private static Object constructorLock` should be final. In fact, code 
inspection flags this as a warning since code synchronizes on it.

- The standard Level constants should be instantiated in a static initializer 
like in my original code. Otherwise the order they are instantiated in is 
unpredictable, and DEBUG (for example) may even have a different ordinal each 
time the JVM starts. 

- Level isn't abstract. However, you use `new Level("xxx", n) {}` (brackets) 
for Level.OFF, ExtendedLevels.NOTE, and ExtendedLevels.DETAIL, but you use `new 
Level("xxx", n)` (no brackets) for other levels. IMO, Level should be abstract 
(so that there's always exactly one instance of every class that extends Level, 
just like a real enum), and the levels should all use {} to construct. However, 
if we don't make Level abstract, then we should remove {} from OFF, NOTE, and 
DETAIL because it's unnecessary.

- The way StdLevel appears in the middle of Level separates its static fields 
from its instance fields, constructor, and methods. It makes it difficult to 
read. I have to scroll pass StdLevel to see the rest of Level. Can we please 
move StdLevel to the bottom of Level?

- This is more personal preference, but I don't like abbreviating things in 
class names. What is Std? We may know, but does everyone? To someone unfamiliar 
with English, Standard is easy to translate, but they have to first figure out 
that Std is short for Std. Can be please un-abbreviate this to StandardLevel?

- I disagree with this approach:

if (levels.containsKey(name)) {
Level level = levels.get(name);
if (level.intLevel() != intLevel) {
throw new IllegalArgumentException("Level " + name + " has 
already been defined.");
}
ordinal = level.ordinal;
}

  This allows multiple Levels with the same name/intLevel to be instantiated, 
which prevents equality testing (level == Level.OFF) from being 100% 
deterministic. It should really be this:

if (levels.containsKey(name)) {
throw new IllegalArgumentException("Level " + name + " has 
already been defined.");
}

- I think we should make all of the methods of Level final. Custom levels 
shouldn't be able to change their behavior, IMO. Alternatively, if we don't 
make Level abstract, we should make it final.

- Level has no JavaDoc. The Level constants in Level have no JavaDoc. That 
needs to be fixed.

- I'm still not convinced StdLevel/StandardLevel is necessary. It seems like an 
anti-pattern to me. From what I can tell (please let me know if I'm missing 
something), StdLevel's entire purpose is to allow us to still switch on the 
standard levels. I think that's a bad reason to create an enum whose constants 
mirror Level. The primary problem with the StdLevel is that the conversion from 
a Level to a StdLevel in many cases happens __on every logging event__. That's 
going to be hugely inefficient. Really, when a custom Level is created, it 
should be created with an equivalent standard Level (or StdLevel). There are 
several ways to accomplish this that are open to discussion, but I don't think 
the current StdLevel.getStdLevel is the right approach. One alternative:

private final Level standardLevel;

protected Level(String name, int level, Level mapToOtherFrameworksAs) {
this(name, level);
this.standardLevel = mapToOtherFrameworksAs;
}

private Level(String name, int level) {
// same as now
this.standardLevel = this;
}

public final Level getStandardLevel() {
return this.standardLevel;
}

This does, admittedly, have some problems. Another alternative that I could 
also be happy with that keeps the StandardLevel enum:

private final StandardLevel standardLevel;

protected Level(String name, int level, StandardLevel 
mapToOtherFrameworksAs) {
this(name, level);
this.standardLevel = mapToOtherFrameworksAs;
}

private Level(String name, int level) {
// same as now
this.standardLevel = this;
}

public final StandardLevel getStandardLevel() {
return this.standardLevel;
}

Nick

On Jan 26, 2014, at 1:38 PM, Ralph Goers wrote:

> I’ve committed the changes.  Take a look at ExtendedLevels.java, 
> ExtendedLevelTest.java and log4j-customLevel.xml in the log4j-core test 
> directories to see how it works.
> 
> Ralph
> 
> On Jan 26, 2014, at 1:19 AM, Remko Popma  wrote:
> 
>> I'm very curious! Can't wait to see it. Go for it!
>> 
>> On Sunday, January 26, 2014, Ralph Goers  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=“” category=“

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Scott Deboy
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  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  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"  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" 
>> 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=“” 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 
>> > 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 
>> >> 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 
>> >>> wrote:
>> 
>>  On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma 
>>  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
>> >  wrote:
>> >>
>> >> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma
>> >>  wrote:
>> >>>
>> >>> Gary,
>> >>>
>> >>> I think that's a very cool idea!
>> >>> 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
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  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"  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"  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=“” 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  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  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  
> >>> wrote:
> 
>  On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma  
>  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  
> > wrote:
> >>
> >> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma  
> >> 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. 
> >> (

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
I’ve committed the changes.  Take a look at ExtendedLevels.java, 
ExtendedLevelTest.java and log4j-customLevel.xml in the log4j-core test 
directories to see how it works.

Ralph

On Jan 26, 2014, at 1:19 AM, Remko Popma  wrote:

> I'm very curious! Can't wait to see it. Go for it!
> 
> On Sunday, January 26, 2014, Ralph Goers  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=“” 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  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  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  wrote:
>>> On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma  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  
>>> wrote:
>>> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma  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  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, 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
Never mind I see you just committed. :-)

I'll review and provide feedback if necessary.

N

On Jan 26, 2014, at 1:36 PM, Nick Williams wrote:

> Can you post a diff or the related files somewhere? Obviously it can be 
> tweaked after commit if necessary, but I'd like to see if there's anything 
> major that sticks out to me before you commit.
> 
> Thanks,
> 
> Nick
> 
> On Jan 26, 2014, at 2:57 AM, Ralph Goers 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=“” 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  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  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  wrote:
 On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma  
 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  
 wrote:
 On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma  
 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  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

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Nick Williams
Can you post a diff or the related files somewhere? Obviously it can be tweaked 
after commit if necessary, but I'd like to see if there's anything major that 
sticks out to me before you commit.

Thanks,

Nick

On Jan 26, 2014, at 2:57 AM, Ralph Goers 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=“” 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  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  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  wrote:
>>> On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma  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  
>>> wrote:
>>> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma  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  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

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Scott Deboy
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"  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" 
> 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="" 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 
> 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  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 
> wrote:
> 
>  On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma 
> 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

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Scott Deboy
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"  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=“” 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 
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  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 
wrote:

 On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma 
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 
wrote:
>>
>> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma 
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 
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

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Remko Popma
I'm very curious! Can't wait to see it. Go for it!

On Sunday, January 26, 2014, Ralph Goers  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=“” 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.go...@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 
> >
> 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 
> wrote:
>
>> On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma 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 wrote:
>>
>> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma 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  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 

Re: Enums and Custom Levels - completed.

2014-01-26 Thread Ralph Goers
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=“” 
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  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  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  wrote:
>> On Fri, Jan 24, 2014 at 11:48 AM, Remko Popma  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  
>> wrote:
>> On Thu, Jan 23, 2014 at 10:45 PM, Remko Popma  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  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:
>> 
>> 
>>