tags:

views:

59

answers:

2

At the end of my Python program, I'd like to be able to get a summary of the number of items logged through the standard logging module. I'd specifically like to be able to get a count for each specified name (and possibly its children). E.g. if I have:

input_logger = getLogger('input')
input_logger.debug("got input1")
input_logger.debug("got input2")
input_logger.debug("got input3")

network_input_logger = getLogger('input.network')
network_input_logger.debug("got network input1")
network_input_logger.debug("got network input2")

getLogger('output')
output_logger.debug("sent output1")

Then at the end I'd like to get a summary such as:

input: 5
input.network: 2
output: 1

I'm thinking, by calling a getcount() method for a logger or a handler.

What would be a good way to achieve this? I imagine it would involve a sub-class of one of the classes in the logging module, but I'm not sure what would be the best way to go.

+2  A: 

Using a decorator could be pretty elegant, I haven't tested this but something like this could work:

class myDecorator(object):
    def __init__(self, inner):
        self.inner = inner
        self.log = {}

    def __getattr__(self,name):
        self.log[name] = self.log.get(name,0)+1
        return getattr(self.inner,name)

    def __setattr__(self,name,value):
        setattr(self.inner,name,value)

I am realizing that you didn't want to log the number of calls to each method but calls to each different logger. All the same I think a decorator could be pretty elegant.

I don't think I've had enough sleep, the idea would be to wrap calls to your logger, I am mixing the use of a decorator with the decorator pattern. (Actually a mix of the pattern and the syntax would be a great answer)

Here is a more complete solution. I'm sorry I realized I was the someone that was wrong on the internet.

class LoggerLogger(object):
    def __init__(self,inner,name):
        self.inner = inner
        self.calls = 0
    def __call__(self,*args,**kwargs):
        self.calls += 1
        return self.inner(*args,**kwargs)


def loggerDecorator(func):
    def inner(name):
        logger = func(name)
        logger.debug = LoggerLogger(logger.debug,name)
    return inner

getLogger = loggerDecorator(getLogger)
Michael
+1 For including example!!!
David Relihan
+1  A: 

I think the decorator pattern might be the cleanest method to implement this.

You will pass an instance of Logger into the LoggerDecorator which will have the same interface as the logger. When one of the methods are called then increment a member variable as appropriate. Then implementing the getCount() method will be trivial.

Here is a reference on implementing decorator in Python:

http://wiki.python.org/moin/DecoratorPattern

David Relihan