Making a logging handler that produces context.

2013-01-14 Thread Antoon Pardon

I have some in house code for which I am considering replacing the
logging code
with something that uses the logging module.

The code is typically used as a cron job with everything higher than
info logged to
a file and everything higher than warning logged to stderr.

However there is one thing the in-house log code does, that seems
difficult to do
with the logging module, provide some context. The in-house handlers
give the
possibilty to specify the number of lines of context the hander can provide.

So the following code:

Logger(fn = file.log, level = info)
Logger(fl = stderr, level = warning, context = 2)

log(INFO, line 1)
log(INFO, line 2)
log(INFO, line 3)
log(INFO, line 4)
log(WARNING, line 5)

Will sent something like the following lines to stderr:

INFO: line 3
INFO: line 4
WARNING: line 5

I tried the code below, but that produced the same
as the ordinary StreamHandler.

class ContextStreamHandler (StreamHandler):

def __init__(self, stream=None, context = 5):
self.recqueue = deque([], context)
StreamHandler.__init__(self, stream)
#__init__

def handle(self, record):
print(CONTEXT HANDLER)
rv = self.filter(record)
if rv:
self.acquire()
try:
for rec in self.recqueue:
self.emit(rec)
self.recqueue.clear()
self.emit(record)
finally:
self.release
else:
self.recqueue.append(record)
return rv
#handle
#ContextStreamHandler


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Making a logging handler that produces context.

2013-01-14 Thread Peter Otten
Antoon Pardon wrote:

 I have some in house code for which I am considering replacing the
 logging code with something that uses the logging module.

 However there is one thing the in-house log code does, that seems
 difficult to do with the logging module, provide some context. The 
 in-house handlers give the possibilty to specify the number of lines of
 context the hander can provide.

 So the following code:

 Logger(fl = stderr, level = warning, context = 2)
 
 log(INFO, line 1)
 log(INFO, line 2)
 log(INFO, line 3)
 log(INFO, line 4)
 log(WARNING, line 5)
 
 Will sent something like the following lines to stderr:
 
 INFO: line 3
 INFO: line 4
 WARNING: line 5
 
 I tried the code below, but that produced the same
 as the ordinary StreamHandler.
 
 class ContextStreamHandler (StreamHandler):
 
 def __init__(self, stream=None, context = 5):
 self.recqueue = deque([], context)
 StreamHandler.__init__(self, stream)
 #__init__
 
 def handle(self, record):
 print(CONTEXT HANDLER)
 rv = self.filter(record)
 if rv:
 self.acquire()
 try:
 for rec in self.recqueue:
 self.emit(rec)
 self.recqueue.clear()
 self.emit(record)
 finally:
 self.release
 else:
 self.recqueue.append(record)
 return rv
 #handle
 #ContextStreamHandler

It turns out the logic of the above is correct. The problem is that the 
handler has to see the INFO-level records while the filter() method has to 
reject them. The following configuration seems to achieve that:

import logging
from collections import deque

class ContextStreamHandler(logging.StreamHandler):
def __init__(self, stream=None, context=5):
self.record_queue = deque([], context + 1)
logging.StreamHandler.__init__(self, stream)
def handle(self, record):
rv = self.filter(record)
self.record_queue.append(record)
if rv:
self.acquire()
try:
for record in self.record_queue:
self.emit(record)
self.record_queue.clear()
finally:
self.release()
return rv

class LevelFilter(logging.Filter):
def __init__(self, level, name=):
logging.Filter.__init__(self, name)
self._filter_level = level
def filter(self, record):
return record.levelno = self._filter_level

if __name__ == __main__:
root = logging.getLogger()
root.setLevel(logging.INFO)

handler = ContextStreamHandler(context=2)
handler.addFilter(LevelFilter(logging.WARN))

root.addHandler(handler)

for i in range(20):
if i % 5:
root.info(message #%d % i)
else:
root.warn(MESSAGE #%d % i)


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Making a logging handler that produces context.

2013-01-14 Thread Antoon Pardon
Op 14-01-13 13:38, Peter Otten schreef:
 It turns out the logic of the above is correct. The problem is that the 
 handler has to see the INFO-level records while the filter() method has to 
 reject them. The following configuration seems to achieve that:

I see, I thought trowing away logrecords of too low a level was also
done by the filter method.
But if I now understand correctly logrecords of too low a level are
thrown away earlier and
don't even reach the handle method.

Thanks for the insight.

-- 
Antoon Pardon
-- 
http://mail.python.org/mailman/listinfo/python-list