You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by Elias Ross <er...@m-qube.com> on 2004/01/28 08:45:45 UTC

Thoughs on Level.java

On Tue, 2004-01-27 at 22:58, Elias Ross wrote:

>   Level ALWAYS = new Level(ALWAYS_INT, "INFO", 7);

Okay, looking at the JavaDoc, Level doesn't have a public constructor.
Why not?  At first glace it didn't make a whole lot of sense.  I then
realized it must have been done this way to allow configuration settings
like this:

  <level value="TRACE" class="org.somebody.CustomLevel" />

What Log4J does is load the class, then calls the toLevel(String) method
to return an actual object.  For this you need to create an overridden
Level.toLevel(String) method, which is part of the Level class. 

Personally, I think it rather annoying to have to build both
toLevel(String) and toLevel(int) methods.  The latter 'int' one doesn't
seen to be used in Log4J at all; the 'String' is only necessary when
converting DEBUG/ERROR/etc. to a real Level object.  Of course writing
those methods is trivial, but it might have worked to just as well to
design custom Levels to look like:

  <level class="org.somebody.CustomLevel#ALWAYS" />  (no value)

Where ALWAYS is a static member variable of an interface or class. 
"CustomLevel" wouldn't necessarily need to implement Level.  (If it did,
then maybe the "toLevel" method would be called, otherwise the member
variable would be retrieved.)

If you need a custom level for a certain class, you could make one up,
define it as a member and not have to write a separate class or
conversion routine.  E.g.:

public class MyClass { 
  
  public static Level ONETIME = new Level(100, "ONETIME", 7)

  public MyClass() {
    Logger.log(ONETIME, "One time message");
  }
}

I think it is confusing for people to have to subclass Level, when
really what they are really trying to do is create not just a Level, but
a collection of Levels.  It seems messy.

Just a humble thought...


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Re: Thoughs on Level.java

Posted by Ceki Gülcü <ce...@qos.ch>.
Barry,

I think that the "always" printing functionality could be of general use. 
There are several ways of approaching this.

1) Extending Logger (category) As you have done. Casual users are strongly 
discouraged from extending the Logger class. A casual user is defined as 
any developer who is not willing to spend the following 3 weeks dealing 
with the ensuing problems.

2) Add a new Level called ALWAYS. Give the ALWAYS level the highest 
possible value, that is Integer.MAX_VALUE, the same value as OFF. Write a 
wrapper for Logger class which adds the "always" methods you want. Those 
methods would use the ALWAYS level.

3) We, the log4j developers could, add the always methods. Whether we do 
this or nor depends on the opinion of the other committers/users.

I hope this helps.

At 02:58 PM 1/30/2004 -0500, Barry Sheward wrote:
>Ceki,
>
>Here is a copy of my previous email...
>
>         Hi,
>
>         We use Log4J extensively and find that sometimes we alwayswant
>         to log a message, but the message is simply for
>         informationalpurposes. Using Logger/Category.fatal() would
>         potentially frightenusers, but using Logger/Category.info() may
>         not show up if they havereconfigured logging.
>
>         While it would be possible to save the priority for thecategory,
>         change the priority for the category, log the message andthen
>         restore the priority for the category, this seemed
>         veryinefficient both in terms of lines of code and run-time
>         performance.
>
>         So, I developed the following four (incredibly simple)methods,
>         which regardless of the current priority of theLogger/Category,
>         will always log the message. The diff is from the1.2.8 source.
>
>         I hereby donate this code to the Apache Software
>         Foundation.Please consider adding these methods to Log4J.
>
>         Regards,
>
>         Barry Sheward
>

-- 
Ceki Gülcü

      For log4j documentation consider "The complete log4j manual"
      ISBN: 2970036908 http://www.qos.ch/shop/products/clm_t.jsp  



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Re: Thoughs on Level.java

Posted by Barry Sheward <ba...@sequation.com>.
Ceki,

Here is a copy of my previous email...
        
        Hi,
        
        We use Log4J extensively and find that sometimes we alwayswant
        to log a message, but the message is simply for
        informationalpurposes. Using Logger/Category.fatal() would
        potentially frightenusers, but using Logger/Category.info() may
        not show up if they havereconfigured logging.
        
        While it would be possible to save the priority for thecategory,
        change the priority for the category, log the message andthen
        restore the priority for the category, this seemed
        veryinefficient both in terms of lines of code and run-time
        performance.
        
        So, I developed the following four (incredibly simple)methods,
        which regardless of the current priority of theLogger/Category,
        will always log the message. The diff is from the1.2.8 source.
        
        I hereby donate this code to the Apache Software
        Foundation.Please consider adding these methods to Log4J.
        
        Regards,
        
        Barry Sheward
        
        
        1037a1038,1111
        >
        >       /**
        >     Log a message object with the {@link Priority#INFOINFO}
        priority
        >     regardless of whether <code>INFO</code> output isenabled
        for
        >     this category.
        >
        >     <p>This method converts the message object
        >     (passed as parameter) to a string by invoking
        theappropriate
        >     {@link ObjectRenderer}. It then proceeds to call all the
        >     registered appenders in this category and also higherin
        the
        >     hierarchy depending on the value of the additivity flag.
        >
        >     <p><b>WARNING</b> Note that passing a {@linkThrowable} to
        this
        >     method will print the name of the<code>Throwable</code>
        but no
        >     stack trace. To print a stack trace use the
        {@link#debug(Object,
        >     Throwable)} form instead.
        >
        >     @param message the message object to log. */
        >   public
        >   void always(Object message) {
        >       forcedLog(FQCN, Priority.INFO, message, null);
        >   }
        >
        >
        >   /**
        >    Log a message object with the <code>INFO</code>priority
        including
        >    the stack trace of the {@link Throwable}<code>t</code>
        passed as
        >    parameter regardless of whether <code>INFO</code>priority
        output
        >    is enabled for this category.
        >
        >    <p>See {@link #always(Object)} form for more
        detailedinformation.
        >
        >    @param message the message object to log.
        >    @param t the exception to log, including its stacktrace. 
        */
        >   public
        >   void always(Object message, Throwable t) {
        >       forcedLog(FQCN, Priority.INFO, message, t);
        >   }
        >
        >     /**
        >     Log a message object with the specified priority
        >     regardless of whether the specified priority output
        isenabled for
        >     this Category.
        >
        >    <p>See {@link #always(Object)} form for more
        detailedinformation.
        >
        >     <p><b>WARNING</b> Note that passing a {@linkThrowable} to
        this
        >     method will print the name of the<code>Throwable</code>
        but no
        >     stack trace. To print a stack trace use the
        {@link#debug(Object,
        >     Throwable)} form instead.
        >
        >     @param message the message object to log.
        >     @param priority the priority to log the message at. */
        >   public
        >   void always(Object message, Priority priority) {
        >       forcedLog(FQCN, priority, message, null);
        >   }
        >
        >
        >   /**
        >    Log a message object with the specified priorityincluding
        >    the stack trace of the {@link Throwable}<code>t</code>
        passed as
        >    parameter regardless of whether specified priority output
        >    is enabled for this Category.
        >
        >    <p>See {@link #debug(Object)} form for more
        detailedinformation.
        >
        >    @param message the message object to log.
        >    @param t the exception to log, including its stack trace.
        >    @param priority the priority to log the message at. */
        >   public
        >   void always(Object message, Throwable t, Prioritypriority) {
        >       forcedLog(FQCN, priority, message, t);
        >   }
        

On Fri, 2004-01-30 at 15:03, Ceki Gülcü wrote:
> At 02:00 PM 1/30/2004 -0500, Barry Sheward wrote:
> >So Ceki, how would you go about trying to do what I want to do?
> 
> 
> >The alternative to adding four methods to Category is having to subclass
> >Level to include a new Level and use Category.log( Level, ... ) or
> >subclass Category too.
> >
> >Either approach will eventually end up with us writing wrappers around
> >Log4J, which I believe is something that you have argued against in the
> >past (http://www.qos.ch/logging/thinkAgain.html).
> 
> My argument was against using commons-logging, in particular its 
> classloader based discovery mechanism. I have no beef with wrapping the 
> Logger class.  Actually, my book lists several cases where wrapping can be 
> useful as well as the pitfalls involved in wrapping the Logger class.
> 
> >Are we the only ones who want this functionality?
> 
> Apologies, but what functionality is that exactly?
-


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Re: Thoughs on Level.java

Posted by Ceki Gülcü <ce...@qos.ch>.
At 02:00 PM 1/30/2004 -0500, Barry Sheward wrote:
>So Ceki, how would you go about trying to do what I want to do?


>The alternative to adding four methods to Category is having to subclass
>Level to include a new Level and use Category.log( Level, ... ) or
>subclass Category too.
>
>Either approach will eventually end up with us writing wrappers around
>Log4J, which I believe is something that you have argued against in the
>past (http://www.qos.ch/logging/thinkAgain.html).

My argument was against using commons-logging, in particular its 
classloader based discovery mechanism. I have no beef with wrapping the 
Logger class.  Actually, my book lists several cases where wrapping can be 
useful as well as the pitfalls involved in wrapping the Logger class.

>Are we the only ones who want this functionality?

Apologies, but what functionality is that exactly?


-- 
Ceki Gülcü

      For log4j documentation consider "The complete log4j manual"
      ISBN: 2970036908 http://www.qos.ch/shop/products/clm_t.jsp  



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Re: Thoughs on Level.java

Posted by Barry Sheward <ba...@sequation.com>.
So Ceki, how would you go about trying to do what I want to do?

The alternative to adding four methods to Category is having to subclass
Level to include a new Level and use Category.log( Level, ... ) or
subclass Category too.

Either approach will eventually end up with us writing wrappers around
Log4J, which I believe is something that you have argued against in the
past (http://www.qos.ch/logging/thinkAgain.html).

Are we the only ones who want this functionality?

On Wed, 2004-01-28 at 07:32, Ceki Gülcü wrote:
> At 11:45 PM 1/27/2004 -0800, Elias Ross wrote:
> >On Tue, 2004-01-27 at 22:58, Elias Ross wrote:
> >
> > >   Level ALWAYS = new Level(ALWAYS_INT, "INFO", 7);
> >
> >Okay, looking at the JavaDoc, Level doesn't have a public constructor.
> >Why not?  At first glace it didn't make a whole lot of sense.
> 
> Level does not have a public a constructor because Level objects are 
> flyweights. The Level class enforces the fact that there is only once and 
> only once instance of Level.INFO, one instance of Level.DEBUG etc. within a 
> given JVM.


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Re: Thoughs on Level.java

Posted by Ceki Gülcü <ce...@qos.ch>.
At 11:45 PM 1/27/2004 -0800, Elias Ross wrote:
>On Tue, 2004-01-27 at 22:58, Elias Ross wrote:
>
> >   Level ALWAYS = new Level(ALWAYS_INT, "INFO", 7);
>
>Okay, looking at the JavaDoc, Level doesn't have a public constructor.
>Why not?  At first glace it didn't make a whole lot of sense.

Level does not have a public a constructor because Level objects are 
flyweights. The Level class enforces the fact that there is only once and 
only once instance of Level.INFO, one instance of Level.DEBUG etc. within a 
given JVM.


-- 
Ceki Gülcü

      For log4j documentation consider "The complete log4j manual"
      ISBN: 2970036908 http://www.qos.ch/shop/products/clm_t.jsp  



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org