[slf4j-dev] Re: TRACE level

Ceki Gülcü listid at qos.ch
Mon Jul 4 21:57:05 CEST 2005



Greg, thank you for your input.

In response to the discussions here and previously identified use
cases, I've just committed the Marker, StarMarker and CompositeMarker
classes to the experimental branch [1] of SLF4J. A Marker is
basically a name. Here is a basic (simplified) implementation.

package org.slf4j;

public class Marker {

   static Map markerMap = new Hashtable();
   String name;

   private Marker(String name) {
     this.name = name;
   }

   public static final Marker getMarker(String name) {
     if (name == null) {
       throw new IllegalArgumentException("Marker name cannot be null");
     }

     Marker marker = (Marker) markerMap.get(name);
     if (marker == null) {
       marker = new Marker(name);
       markerMap.put(name, marker);
     }

     return marker;
   }

   public String getName() {
     return name;
   }

   public boolean matches(Marker marker) {
     if ((this == marker)) {
       return true;
     }

     return false;
   }

   public boolean matches(String name) {
     if (this.name.equals(name)) {
       return true;
     }
     return false;
   }
}


Markers allow log statements to be marked in user-chosen ways.

For example, for the HttpRequest class you mentioned, we can now
write:


package org.mortbay.jetty;

import org.slf4j.Marker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class HttpRequest {

   Logger logger = LoggerFactory.getLogger(HttpRequest.class);

   static final Marker HEADER = Marker.getMarker("header");

   void doRequest() {
     logger.debug("Request URI is {}", uri);

     logger.debug(HEADER, "Headers follow.");
     for(int i = 0; i < header.length; i++) {
       logger.debug(HEADER, "{}: {}", header[i].getName(), 
header[i].getValue());
     }

     ... do real work
   }
}

If the org.mortbay.jetty.HttpRequest is enabled for the DEBUG level,
than all log statements in doRequest() will be printed. However, the
user can chose to instruct the logging system to those disable log
statements of level DEBUG marked with the HEADER marker.

This approach has the advantage of allowing multiple markings to
co-exist without interference. Nothing prevents the developer from
writing log statements with different markings.

As for the ignore() method, the logging system can be instructed to
ignore the stack traces for a given exception using a special
marking. For example,

  try {
    access some IOStream
  } catch(IOException e) {
    logger.debug(NO_STACK_TRACE, "Exception while talking to peer", e);
  }


One of challenges in the design is to allow for markers to contain child
markers. For example,

   Marker blue = Marker.getMarker("blue");
   Marker red  = Marker.getMarker("red");
   Marker colors = Marker.getCompositeMarker("colors");
   colors.add(blue);
   colors.add(red);

   blue.matches("blue"); // this is true
   red.matches("red"); // also true
   red.matches("blue"); // false
   colors.matches("colors"); // true
   colors.matches("red"); // also true
   colors.matches("blue"); // true


I am tempted to use the Composite pattern from the Go4 book although it
is not totally clear whether the pattern could be judiciously applied
here.

In the HttpRequest example above, some headers could be marked with an
additional marker, say IMPORTANT_HEADER. Thus, the user could chose
between printing all headers, no headers, or only important headers.


So, wdyt?

[1] http://svn.slf4j.org/viewcvs/slf4j/branches/marker-experiment/

At 12:44 AM 7/3/2005, Greg Wilkins wrote:
>Ceki Gülcü wrote:
>
> > <request>
> >
> >   Can anyone think of a class which makes uses of both trace() and
> >   debug()? If so, could you please provide a URL?
> >
> > </request>
>
>The use case I have for trace (or I prefer to call it verbose) is
>the case when I have an object that I wish to log, but that I have
>a choice of the amount of detail that can be logged.
>
>Examples include:
>
>   HttpRequest:   log just the method and URI or all the headers.
>   Document:      log just the URI of the document or dump all of the XML.
>
>I see this as quiet related to ignore, where the developer has
>an exception object to log, but has to choose between clogging the
>log with excess information or hiding something valuable.
>
>With the case of ignore, the developer has a clear intent that
>can be signalled in the signature - to assist a later decision on
>how much detail to display.   This can be done because the
>logging system has the ability to expand the Exception statck trace or
>just call toString on it.
>
>With other objects, the logging system will only call toString on
>them, so if the developer wants to report an object in detail then
>they must do so explicitly - it would be good if they could protect
>that with an if(log.isVerboseEnabled()) or an if(log.isTraceEnabled())
>
>But then another solution would be to have a logger that supports
>customizable object formatters....
>
>cheers

-- 
Ceki Gülcü

   The complete log4j manual: http://www.qos.ch/log4j/





More information about the slf4j-dev mailing list