业务代码用的是python原生的logging模块。
现在碰到这么一个需求:当处理error级别日志时,将错误信息统一进行某种操作。比如发送到一个消息队列里。不能改变现有的业务代码结构。
首先想到的是logging模块是否有类似回调方法的设定。经过查询,果然logging中有一个handler属性,可以自定义对异常信息的处理。logging自带几种handler,比如StreamHandler、FileHandler等。为了将功能最大化,我们选择其中的NullHandler,它什么都不干。我们实现一个新的类来继承它,再在其中自定义我们的逻辑。
代码:
# encoding: utf-8
import logging
from logging import NullHandler
class MyHandler(NullHandler):
def handle(self, record):
# print "=====,%s" % (str(record.__dict__))
msg = record.msg
msg = record.message # 在服务中该字段叫'message'
if record.levelno == 10: # DEBUG
pass
elif record.levelno == 20: # INFO
pass
elif record.levelno == 30: # WARNING
pass
elif record.levelno == 40: # ERROR
print u"在这里执行对error的处理:%s" % msg
elif record.levelno == 50: # CRITICAL
print u"在这里执行对critical的处理:%s" % msg
logging.getLogger("").setLevel(logging.NOTSET)
logging.basicConfig()
logging.getLogger("").addHandler(MyHandler())
if __name__ == "__main__":
logging.debug(u"这是一条 DEBUG 信息")
logging.info(u"这是一条 INFO 信息")
logging.warning(u"这是一条 WARNING 信息")
logging.error(u"这是一条 ERROR 信息")
logging.critical(u"这是一条 CRITICAL 信息")
上述中的“logging.basicConfig()”一行主要实现这么一个功能:由于我们为logging设置了自定义的handler,那么所有的错误级别日志,都需要我们在handle方法中自定义。但是我们现在只想对error级别以上的错误进行预处理,对于更低级别的日志,我们希望它就按原来的样式原封不动输出就好。经过查看源代码,发现可以用 basicConfig()方法,这个方法写在logging模块原生的debug()、info()、warning()...... 等所有级别的方法中,它实现的是:如果发现用户没有设置任何handler,那么进行若干步初始化设置,就是这些初始化设置实现了我们在控制台看到的不同颜色、缩进等样式输出的日志。现在我们首先实现logging.basicConfig(),再添加自定义的handler,那两块逻辑就同时实现了。
正因为如此,
logging.basicConfig()
logging.getLogger("").addHandler(MyHandler())
这两行的顺序不能调换。