目录

使用Filter过滤python中的日志输出

事情是这样的,我写了一个tornado的服务,过程当中我用logging记录一些内容,由于一开始并没有仔细观察tornado自已的日志管理,所以我就一般用debug来记录普通日志,error记录有问题的日志,但是当服务跑起来以后才发现,tornado的访问日志的级别是info,也就是20,debug是10的,所以如果我定义了日志的级别是debug,那么默认情况下肯定也会输出到日志文件中的。 但是我现在并不关心访问日志,而且由于我这个服务可能每时每刻都会有访问,这样在我对日志信息进行搜索的时候就会有很大的影响。 该怎么办呢?

有以下几种办法

修改初始化日志时的级别

一种是修改我初始化时定义的日志级别,定成比info还高的,这样就不会再记录info的日志了 但是这种方法需要我将之前记录日志的debug方法也要修改为比info更高的级别,也就是要大于20。修改的地方有点多,且我已经习惯了用debug来记录,改起来成本有点大。

修改tornado 本身

可以到site-packages中修改tornado下的web.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def log_request(self, handler):
    """Writes a completed HTTP request to the logs.

    By default writes to the python root logger.  To change
    this behavior either subclass Application and override this method,
    or pass a function in the application settings dictionary as
    ``log_function``.
    """
    if "log_function" in self.settings:
        self.settings["log_function"](handler)
        return
    if handler.get_status() < 400:
        log_method = access_log.info
    elif handler.get_status() < 500:
        log_method = access_log.warning
    else:
        log_method = access_log.error
    request_time = 1000.0 * handler.request.request_time()
    log_method("%d %s %.2fms", handler.get_status(),
               handler._request_summary(), request_time)

其中log_method = access_log.info 可以修改它,access_log在log.py中定义,

access_log = logging.getLogger(“tornado.access”)

这里可以定义access_log的级别,然后再修改log_request的实现,想想都复杂,而且直接修改site-packes里的库文件是一个比较笨的方法,日后迁移会发生很多莫名其妙的问题。

使用logging.Filter设置过滤规则

其实logging早就有了相应的解决方法,logging库中有一个Filterer类,logging库中的Handler和Logger类都是继承自Filter类的 Filter类中有三个方法,addFilter(filter),removeFilter(filter)filter(record)方法,这里主要使用addFilter和filter方法。

addFilter方法需要一个filter对象,这里我定义一个新的类,并且重写filter方法, 将日志名为tornado.access且日志级别是20的过滤掉。

1
2
3
4
5
class NoParsingFilter(logging.Filter):
    def filter(self, record):
        if record.name == 'tornado.access' and record.levelno == 20:
            return False
        return True

这样我在初始化 logging对象以后,将这个过滤器添加进去

1
2
logobj = logging.getLogger('server')
logobj.addFilter(NoParsingFilter())

这样添加一个过滤以后日志就会随心所欲的按照自已的方式来记录了,record也是logging的一个类LogRecord,常用的属性有name, level, pathname, lineno,msg, args, exc_info name 就是初始化logger对象时传入的名字 level 是级别 pathname 是哪个文件输出的这行日志 lineno 是行号 msg 是日志本身