Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Summary count for Python logging

Tags:

python

logging

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.

like image 639
Craig McQueen Avatar asked May 17 '10 07:05

Craig McQueen


People also ask

What is StreamHandler in Python logging?

The StreamHandler class, located in the core logging package, sends logging output to streams such as sys. stdout, sys. stderr or any file-like object (or, more precisely, any object which supports write() and flush() methods).

What are the five levels of logging in Python?

Log messages can have 5 levels - DEBUG, INGO, WARNING, ERROR and CRITICAL. They can also include traceback information for exceptions.


2 Answers

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)
like image 56
Michael Avatar answered Sep 30 '22 11:09

Michael


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

like image 21
Robben_Ford_Fan_boy Avatar answered Sep 30 '22 12:09

Robben_Ford_Fan_boy