Adding new format specifiers to the logging module. In this example, it's for the user name and the name of the function that logged the message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | # xlog.py
import logging
# Adding the 'username' and 'funcname' specifiers
# They must be attributes of the log record
# Custom log record
class OurLogRecord(logging.LogRecord):
def __init__(self, *args, **kwargs):
logging.LogRecord.__init__(self, *args, **kwargs)
self.username = current_user()
self.funcname = calling_func_name()
# Custom logger that uses our log record
class OurLogger(logging.getLoggerClass()):
def makeRecord(self, *args, **kwargs):
return OurLogRecord(*args, **kwargs)
# Register our logger
logging.setLoggerClass(OurLogger)
# Current user
def current_user():
import pwd, os
try:
return pwd.getpwuid(os.getuid()).pw_name
except KeyError:
return "(unknown)"
# Calling Function Name
def calling_func_name():
return calling_frame().f_code.co_name
import os, sys
def calling_frame():
f = sys._getframe()
while True:
if is_user_source_file(f.f_code.co_filename):
return f
f = f.f_back
def is_user_source_file(filename):
return os.path.normcase(filename) not in (_srcfile, logging._srcfile)
def _current_source_file():
if __file__[-4:].lower() in ['.pyc', '.pyo']:
return __file__[:-4] + '.py'
else:
return __file__
_srcfile = os.path.normcase(_current_source_file())
|
So you want to add new format specifiers to the logging module? Piece of cake, thanks to Vinay Sajip's clean code (Vinay wrote the logging module).
If you save the code above in xlog.py, the following code will work:
<pre> import logging import xlog # register our custom logger
use the new format specifiers
logging.basicConfig( format="%(filename)s: %(username)s says '%(message)s' in %(funcname)s" )
def foo(): logging.getLogger("trace").warn("Hi mom!")
foo() </pre>
This will print: <pre> prompt> python usercode.py usercode.py: charlie says 'Hi mom!' in foo </pre>
Presented as a lightning talk in OSDC::Israel::2006, http://www.osdc.org.il
Python 2.4 Error. Trying to do this with Python 2.4 has the following traceback:
That happens when you use the "root logger" Solution: use a named logger instead of the root logger:
Explanation:
The extended logger class is only used for loggers that haven't been created yet. The root logger (what you get with getLogger() or getLogger('')) is instantiated before the default logger class can be changed.
Hope this helps...
update to this recipe for Python 2.5.