fine grain logging cotrol

Eric S. Johansson esj at harvee.org
Thu Mar 22 11:58:44 EDT 2007


Peter Otten wrote:
> Eric S. Johansson wrote:
> 
>> I need to to be able to conditionally log based on the method the log
>> statement is in and one other factor like a log level.  in order to do
>> so, I need to be able to automatically find out the name of the method
>> and its class but I haven't found out how to do that yet.
>>
>> for example,
>>
>> class catus(Felis):
>>    def Siamese_cat( yowl, purr, demand_food):
>>
>>      ...
>>      log("state of litter box %s"% litter_box.smell, level = 1)
>>
>>
>> If the table of methods logged contains "catus.Siamese_cat", then I
>> would expect to see the output of the log statements in a log file.  If
>> not then I wouldn't see anything in the log.
>>
>> Has somebody done this already?  Is it even possible to do without
>> manually adding the class and method information for every log statement?
>>
>> a related question is using signals for reloading configurations etc.  I
>> have to find any good examples of how to use signals to cause a
>> long-running process to reload external data.  Any good pointers?
> 
> Instead of rolling your own, use the logging package which can handle
> everything but the class info out of the box (levels are spelt as method
> names info(), warn() etc.).

I was planning on using logging.  I've been using syslog for too long
> 
> import logging
> 
> class LoggedType(type):
>     def __new__(mcl, name, bases, classdict):
>         classdict["logger"] = logging.getLogger(name)
>         return type.__new__(mcl, name, bases, classdict)

__new__ is new to me.  took a look at 
http://www.python.org/download/releases/2.2.3/descrintro/#__new__ which 
give me some clue but not enough.  what I get is that in call 
initialization, you add an entry to the class dict (adds new method??). 
I see that name, bases, or classdict are part of the normal class 
construction process and refer to the class under construction.  I'm 
guessing mcl comes from __metaclass__ and defaults to type?

the getLogger creates a logging channel so there is one channel per 
class?  but what selects the class for output or is that a derived 
logger class I need to create?

also, how could one automatically determine the method doing the logging?

> 
> class Felis:
>     __metaclass__ = LoggedType

needed in every top level class?

>     def alpha(self):
>         self.logger.info("felis-alpha")
> 
> class Catus(Felis):
>     def alpha(self):
>         self.logger.info("catus-alpha")
>     def beta(self):
>         self.logger.info("catus-beta")
> 
> if __name__ == "__main__":
>     logging.basicConfig(format="%(name)s.%(funcName)s: %(message)s",
> level=logging.INFO)
>     f = Felis()
>     f.alpha()
>     c = Catus()
>     c.alpha()
>     c.beta()


> 
> If the metaclass bothers you, here's a simpler alternative:

simpler to implement but more error prone.  I like the metaclass model. 
  now if one could fill in the class and method name automatically, life 
would be good.




More information about the Python-list mailing list