java中的接口是类吗
1051
2022-09-05
正确使用Python logging(正确使用筷子的方法)
这篇文章主要参考: 对于主模块, 直接对root logger做logger输出设置. 这样所有模块都会按照root logger的设置进行log 输出.
2. 所有模块, 包括主模块, 都应使用logging.getLogger(__name__)来获得logger实例, 使用getLogger(__name__)获得的logger, 输出的日志能体现出模块的命名空间. 主模块getLogger()调用应放在logging初始化之后.
3. 对于非主模块,不应做logger的初始化配置, 也不应该在模块级上调用getLogger(), 而应该在function中或者class中来调用getLogger().
理由是: 最主要的原因是, log配置应该是主模块的特权. 还有一个理由是, 我们的主module往往是先import非主module, 然后再用logging.config.fileConfig()做初始化, 而fileConfig()缺省会disable已存在的所有logger, 也就是说非主模块级别的那些logger都被禁掉了, 也就无法再用来记日志.
4. 在主模块和非主模块推荐, 都应该使用logger.info()和logger.debug()来记日志, 不推荐使用logging.info()和logging.debug()这样的方法, 后者是用的是root logger, 所有模块都用root, 就无法区分日志是由哪个模块产生的了.
5. 推荐使用 cloghandler.py 的 ConcurrentRotatingFileHandler.
而不是FileHandler 和RotatingFileHandler 和TimedRotatingFileHandler .
理由是 FileHandler, 单文件日志缺点比较多.
而 RotatingFileHandler的问题是, 在windows下当文件大小到达max时, logging操作会报错, 新log有时候就记不进去了. 另外如果多个程序往同一个log文件写, RotatingFileHandler也会报错的, cloghandler.py没这个问题.
而TimedRotatingFileHandler的问题是, 在windows下, 如果log文件在23:59正在被写入, logging操作也会报错, 无法进行log文件重命名, 新log有时候就记不进去了. 当然这个几率要比RotatingFileHandler失败几率小.
参考 长log的format, 我使用的是,
说明: 前面加上####, 这样log parser容易分开不同的log记录. 分隔符使用|而不是逗号, 因为时间串中会包含个逗号的.
formatter = logging.Formatter(fmt='####%(asctime)s|pid=%(process)d|tid=%(thread)d|%(name)s|%(levelname)s|%(message)s')
短log的format, 我使用的是,
shortFormatter = logging.Formatter(fmt='####%(asctime)s|%(name)s|%(levelname)s|%(message)s', datefmt="%H:%M:%S")
7. 关于应用程序如何合并第3方类库的log输出, 比如合并SqlAlchemy的日志.
基本不用特别在意, 只要我们的程序设置了root logger, 应用程序和SqlAlchemy的日志自然会合并输出在root logger的handler中.
==========================
类库的logging的做法
==========================
1.类库logging的使用, 其实和application的非主模块类似.
2.在类库的top level库中, 最好为logger加上NullHandler, 这样即使应用程序根本没做logging配置, 也不会出现未配置logging的警告信息.
=========================
几个有关的函数
==========================
rootLogger = logging.getLogger() #getLogger()不带参数, 得到的即是rootLogger
logging.basicConfig(level=logging.DEBUG) #是一个很顺手的logging配置方案, 输出为stderr, 非常适合在demo和调试程序
logging.config.dictConfig(dict_LOG_CONFIG) #使用dict来初始化logger
logging.config.fileConfig(ini_file) #使用ini文件来初始化logger
==========================
选择合适的logging level
==========================
这里误区也比较多, 很多程序员喜欢滥用error级别. 可最佳日志实践中的介绍,
: 开发人员debug用, 比如记录详尽的业务动作, 比如SQL
INFO : 记录一些关键的动作和数据.
WARN : 用于那些对业务功能已有影响, 但不太严重的情形
ERROR : 仅用于记录那些已影响业务功能的Error或Exception
FATAL : (同CRITICAL)仅用于影响到程序完全不能工作的情况, 比如非法退出
如果还不容易区分, 换另一个角度, WARNING和ERROR级别的问题, 都是需要及时处理.
=========================
dict 配置的写法
==========================
1. 具体 ini 配置文件如何写, 参考
dict_LOG_CONFIG ={ #版本总是1 'version': 1, # 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s' }, }, 'handlers': { 'default': { 'level':'INFO', 'class':'logging.StreamHandler', }, }, 'loggers': { #加一个root logger '': { 'handlers': ['default'], 'level': 'INFO', 'propagate': True }, #加其他logger 'django.request': { 'handlers': ['default'], 'level': 'WARN', 'propagate': False }, }}
==========================
ini 配置的写法
==========================
参考
[loggers] keys=root, web.debug, web.info, web.error# 定义格式化输出[formatters]keys=simpleFormatter, webSimpleFormatter# 定义handler[handlers]keys=consoleHandler,rotateFileHandler, webDebugRotateFileHandler, webInfoRotateFileHandler, webErrorRotateFileHandler, webSMTPHandler#--------------------------------------------------# 实现上面定义的logger模块,必需是[logger_xxxx]这样的形式#--------------------------------------------------# [logger_xxxx] logger_模块名称# level 级别,级别有DEBUG、INFO、WARNING、ERROR、CRITICAL# handlers 处理类,可以有多个,用逗号分开# qualname logger名称,应用程序通过 logging.getLogger获取。对于不能获取的名称,则记录到root模块。# propagate 是否继承父类的log信息,0:否 1:是[logger_root] level=DEBUG handlers=consoleHandler,rotateFileHandler[logger_web.debug]level=DEBUGhandlers=consoleHandler,webDebugRotateFileHandlerqualname=web.debugpropagate=0[logger_web.info]level=INFOhandlers=consoleHandler,webInfoRotateFileHandlerqualname=web.infopropagate=0[logger_web.error]level=ERRORhandlers=consoleHandler,webErrorRotateFileHandler,webSMTPHandlerqualname=web.errorpropagate=0#--------------------------------------------------# 日志格式#--------------------------------------------------# %(asctime)s 年-月-日 时-分-秒,毫秒 2013-04-26 20:10:43,745# %(filename)s 文件名,不含目录# %(pathname)s 目录名,完整路径# %(funcName)s 函数名# %(levelname)s 级别名# %(lineno)d 行号# %(module)s 模块名# %(message)s 消息体# %(name)s 日志模块名# %(process)d 进程id# %(processName)s 进程名# %(thread)d 线程id# %(threadName)s 线程名[formatter_simpleFormatter]format=%(asctime)s|%(name)s|%(threadName)s|%(levelname)s > %(message)s[formatter_webSimpleFormatter]format=%(asctime)s %(clientip)s %(levelname)s > %(message)s#--------------------------------------------------# handler#--------------------------------------------------# [handler_xxxx]# class handler类名# level 日志级别# formatter,上面定义的formatter# args handler初始化函数参数[handler_consoleHandler] class=StreamHandlerlevel=DEBUGformatter=simpleFormatterargs=(sys.stdout,)[handler_rotateFileHandler]class=handlers.RotatingFileHandlerlevel=DEBUGformatter=simpleFormatterargs=('access.log','a',2000000,9)[handler_webDebugRotateFileHandler]class=handlers.RotatingFileHandlerlevel=DEBUGformatter=simpleFormatterargs=('debug.log','a',2000000,9)[handler_webInfoRotateFileHandler]class=handlers.RotatingFileHandlerlevel=INFOformatter=webSimpleFormatterargs=('info.log','a',2000000,9)[handler_webErrorRotateFileHandler]class=handlers.RotatingFileHandlerlevel=ERRORformatter=webSimpleFormatterargs=('error.log','a',2000000,9)[handler_webSMTPHandler]class=handlers.SMTPHandlerlevel=ERRORformatter=webSimpleFormatterargs=('mailhost', 'fromaddr', ('toaddrs1','toaddrs2'), 'subject', ('username','password'))
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~