python日志模块
python的日志记录一般使用logging
标准模块,比较强大,可以设置日志等级level
,添加日志handler
来扩展记录模式,比如streamhandler
、filehandler
、smtphandler
等等,基本不给第三方日志模块留活路。
比如打印到stdout
的日志可以这么写:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import logging
def init_log():
log = logging.getLogger(__name__)
log.setLevel(LOG_LEVEL)
console = logging.StreamHandler(sys.stdout)
console.setLevel(LOG_LEVEL)
fmt = "[%(levelname)s][%(asctime)s][%(process)d]" \
"logger=%(name)s|tag=%(funcName)s:%(filename)s:%(lineno)d|" \
"content=%(message)s"
datefmt = "%Y-%m-%d %H:%M:%S %z"
formatter = logging.Formatter(fmt=fmt, datefmt=datefmt)
console.setFormatter(formatter)
log.addHandler(console)
return log
然后就可以1
2
3
4log.debug('Message')
#log
[DEBUG][2016-11-25 16:23:23 +0000][22486]logger=app.common.init_log|tag=verify******:**********:24|content=Message
也可以使用logging
的配置文件,如logging.conf
1
2logging.config.fileConfig("logging.conf")
logger = logging.getLogger('test')
目前更多使用字典做配置项的
嗯,陪老婆去逛街,回来继续
比如: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
38logger_dict_config = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'console': {
'format': '[%(asctime)s][%(levelname)s] %(name)s '
'%(filename)s:%(funcName)s:%(lineno)d | %(message)s',
'datefmt': '%H:%M:%S',
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'console',
'stream': 'ext://sys.stdout'
},
'error': {
'level': 'ERROR',
'class': 'logging.StreamHandler',
'formatter': 'console',
'stream': 'ext://sys.stderr'
}
},
'loggers': {
'app': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False,
}
}
}
logging.config.dictConfig(get_logging_config(app.config))
_logger = logging.getLogger('app')
Flask日志
启动flask后,除了上述主动打印的服务日志或调试日志外,还会有:1
127.0.0.1 - - [27/Nov/2016 14:15:13] "GET /login HTTP/1.1" 200 -
这个是由werkzeug
模块控制的,在一定情况下需要定制或者重定向标准日志的时候可以1
2
3
4
5
6
7
8
9logger = logging.getLogger('werkzeug')
#仅ERROR级日志打印
logger.setLevel(logging.ERROR)
#关掉日志,仅仅打印服务日志
logger.disabled = True
#修改日志格式,和werkzeug日志在一块,上面关闭的话,也不会显示
from werkzeug._internal import _log
#_log('level','content')
_log('info','[Dirac]{real_ip} {remote_ip} {request_host} [{request_time}] "{request_method} {request_path}" {reqeust_staus_code} {response_time} {uuid}'.format(...)
上面的方法可以关掉werkzeug
日志,只打印自己定义的服务日志,这样可以统一日志格式进行分析,但如果希望替换掉werkzug
日志,则可以修改或者替换掉默认的请求handler
的日志格式,例如1
2
3
4
5
6
7
8
9
10from werkzeug import serving
class LimitLogHandler(serving.WSGIRequestHandler):
def log(self, type, message, *args):
msg = (message % args)
_log(type, '%s - - (Lim) [%s] %s\n' % (self.address_string(),
self.log_date_time_string(),
"{} ... {}".format(msg[:50],msg[-40:])))
app = flask.Flask(__name__)
if __name__ == "__main__":
app.run(debug = True, request_handler = LimitLogHandler)
werkzeug真是个好东西,需要用好并好好读下源码
啥时候才能写出优雅高效的python代码啊?
过滤addFilter
增加过滤器,滤除不需要的log
,上面修改werkzeug
日志也可以滤出默认日志1
2
3
4
5
6class NoParsingFilter(logging.Filter):
#重写filter函数
def filter(self, record):
return not record.getMessage().startswith('[Dirac]')
logger.addFilter(NoParsingFilter())