You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Steve Downey <st...@netfolio.com> on 2002/03/07 02:06:40 UTC

RE: [LOGGING] Request for API change (was RE: [VOTE] Logging 1.0 Release (again))

I'd argue that this is a misuse of a logger. A logger isn't an IO stream and
shouldn't be treated like one. 
Here's how I've implement this kind of thing:


public static void writeMap(Map map, Writer writer)
{
    for(Iterator keys = map.keySet().iterator(); keys.hasNext();)
    {
        String key = (String) keys.next();
        String value = (String) map.get(key);
        writer.print(key);
	  writer.print('=');
	  writer.print(value);
        writer.println();
    }
}

...
if(logger.is{X}Enabled()) {
	StringWriter writer = new StringWriter();
	writeMap(map, writer);
	logger.{X}(writer.toString());
}

Now, If you want to argue that abstracting out those 4 lines of code for
values of X is useful, I'd argue that the marginal utility is low. The
number of cases where you want to dump a Map to a log at levels other than
debug is tiny. 

IOW, at Error, you want a message like "IP address not found for Domain Name
= {}", not a list of all known domain/IP mappings. Similarly for Info "IP
address {} found for Domain Name = {}". Warn is something like "IP address
null for Domain Name = {}". Of course, these are all at the semantic level
above Map.

Map's internal logging should be much sparser. Earth shattering events like
"HashBucket claims 5 elements, but only found 4: Panic!" IE, the whole thing
is FUBAR'd. At least until you get down to Trace level stuff. 

Just my $0.02

> -----Original Message-----
> From: Steven Caswell [mailto:stevencaswell@yahoo.com]
> Sent: Wednesday, March 06, 2002 4:13 PM
> To: 'Jakarta Commons Developers List'
> Subject: [LOGGING] Request for API change (was RE: [VOTE] Logging 1.0
> Release (again))
> 
> 
> I want to revisit one of the issues noted below. A couple of weeks
> before the VOTE was posted I made a request for a couple of these.  I
> agree with not doing the third item (configuration) and can 
> live without
> the second (though arguments for the first are valid for this one as
> well.  But I believe not having the first is a serious drawback.
> 
> > There are a number of suggested changes that are *not* 
> > included, and I propose that we continue to not include them:
> > * Adding a generic "Level" concept (either as a unique class or
> >   as a set of integer constants) to the Log interface.
> > * Adding a log(Level, String) method to the Log interface.
> > * Adding mechanisms to configure loggers through the Log interface.
> > 
> > Going down the path of implementing any of these in the 
> > commons logging wrapper would violate the principle on which 
> > this API was designed, of being a very thin facade over the 
> > facilities of multiple underlying wrapper implementations.
> >
> The lack of a Level concept in the API makes abstraction of 
> logging code
> more difficult than it should be.  For example, suppose I 
> want to write
> a method in a utility class that logs the contents of a Map.  
> This might
> look something like the following:
> 
> public static void logMap(Map mapToLog, Log logger, ??? level)
> {
>     for(Iterator keys = map.keySet().iterator(); keys.hasNext();)
>     {
>         String key = (String) keys.next();
>         String value = (String) map.get(key);
>         if(level == TRACE) logger.trace(key + "=" + value);
>         else if(level == DEBUG) logger.trace(key + "=" + value);
>         else if(level == DEBUG) logger.debug(key + "=" + value);
>         else if(level == INFO) logger.info(key + "=" + value);
>         ...etc for each level
>     }
> }
> 
> The difficulty in this is how to identify the level. Without a level
> concept in the API, the application is forced to invent its own, which
> it shouldn't have to do. Or the application can defined multiple
> versions of the method, one for each level. 
> 
> I disagree that going down the level path would violate the 
> thin façade
> principle.  In fact, the API has already introduced the level 
> concept by
> exposing different level methods (i.e., Log.isTraceenabled(),
> Log.trace(), etc.). Adding a set of constants to consistently identify
> levels would make the already-existing level concept more robust, And
> would make significant isolation of logging code must more 
> reasonable to
> achieve.
> 
> 
> Steven Caswell
> stevencaswell@yahoo.com
> a.k.a Mungo Knotwise of Michel Delving
> "One ring to rule them all, one ring to find them..."
> 
> 
> 
> _________________________________________________________
> Do You Yahoo!?
> Get your free @yahoo.com address at http://mail.yahoo.com
> 
> 
> --
> To unsubscribe, e-mail:   
<ma...@jakarta.apache.org>
For additional commands, e-mail:
<ma...@jakarta.apache.org>

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: [LOGGING] Request for API change (was RE: [VOTE] Logging 1.0 Release (again))

Posted by Steven Caswell <st...@yahoo.com>.




> -----Original Message-----
> From: Steve Downey [mailto:steve.downey@netfolio.com] 
> Sent: Wednesday, March 06, 2002 8:07 PM
> To: 'Jakarta Commons Developers List'
> Subject: RE: [LOGGING] Request for API change (was RE: [VOTE] 
> Logging 1.0 Release (again))
> 
> 
> I'd argue that this is a misuse of a logger. A logger isn't 
> an IO stream and shouldn't be treated like one. 
> Here's how I've implement this kind of thing:
> 
> 
> public static void writeMap(Map map, Writer writer)
> {
>     for(Iterator keys = map.keySet().iterator(); keys.hasNext();)
>     {
>         String key = (String) keys.next();
>         String value = (String) map.get(key);
>         writer.print(key);
> 	  writer.print('=');
> 	  writer.print(value);
>         writer.println();
>     }
> }
> 
> ...
> if(logger.is{X}Enabled()) {
> 	StringWriter writer = new StringWriter();
> 	writeMap(map, writer);
> 	logger.{X}(writer.toString());
> }
> 
> Now, If you want to argue that abstracting out those 4 lines 
> of code for values of X is useful, I'd argue that the 
> marginal utility is low. The number of cases where you want 
> to dump a Map to a log at levels other than debug is tiny. 
> 
Actually, I do log maps quite often.  When I'm developing and debugging,
I frequently want to dump the contents of a map.

However, I don't want this to turn into a discussion of the merits (or
lack thereof :) of logging maps. That was just an example. My desire is
to be able to abstract the logging of anything in general. My rule of
thumb is that when I write the same code more than twice, it is time to
abstract it. And as a good logger, I write lots of logging code more
than once.

BTW, I do agree that your approach to logging the map is more
appropriate. I was coding my example off the top of my head and hadn't
actually thought about a real implementation. But it still doesn't
address how the writeMap method decides which level to use.

> IOW, at Error, you want a message like "IP address not found 
> for Domain Name = {}", not a list of all known domain/IP 
> mappings. Similarly for Info "IP address {} found for Domain 
> Name = {}". Warn is something like "IP address null for 
> Domain Name = {}". Of course, these are all at the semantic 
> level above Map.
> 
> Map's internal logging should be much sparser. Earth 
> shattering events like "HashBucket claims 5 elements, but 
> only found 4: Panic!" IE, the whole thing is FUBAR'd. At 
> least until you get down to Trace level stuff. 
> 
> Just my $0.02
> 
snip
> 
Steven Caswell
stevencaswell@yahoo.com
a.k.a Mungo Knotwise of Michel Delving
"One ring to rule them all, one ring to find them..."



_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>