Python logging 模块和使用经验
来源:互联网 发布:淘宝买家id在哪里看 编辑:程序博客网 时间:2024/05/15 07:50
记录下常用的一些东西,每次用总是查文档有点小麻烦。 py2.7
日志应该是生产应用的重要生命线,谁都不应该掉以轻心
有益原则
级别分离
日志系统通常有下面几种级别,看情况是使用
- FATAL - 导致程序退出的严重系统级错误,不可恢复,当错误发生时,系统管理员需要立即介入,谨慎使用。
- ERROR - 运行时异常以及预期之外的错误,也需要立即处理,但紧急程度低于FATAL,当错误发生时,影响了程序的正确执行。需要注意的是这两种级别属于服务自己的错误,需要管理员介入,用户输入出错不属于此分类。
- WARN - 预期之外的运行时状况,表示系统可能出现问题。对于那些目前还不是错误,然而不及时处理也会变成错误的情况,也可以记为WARN,如磁盘过低。
- INFO - 有意义的事件信息,记录程序正常的运行状态,比如收到请求,成功执行。通过查看INFO,可以快速定位WARN,ERROR, FATAL。INFO不宜过多,通常情况下不超过TRACE的10%。
- DEBUG - 与程序运行时的流程相关的详细信息以及当前变量状态。
- TRACE - 更详细的跟踪信息。DEBUG和TRACE这两种规范由项目组自己定义,通过该种日志,可以查看某一个操作每一步的执行过程,可以准确定位是何种操作,何种参数,何种顺序导致了某种错误的发生
单独目录
日志最好放到单独的日志目录,例如 /var/logs/
下,按照应用分成不同的目录,或者是文件。日志不要放在应用目录下,那样不利于自动化部署和应用升级,备份等。
日志分类
诊断日志,统计日志,审计日志等等,不同用途等日志存储到不同的文件中,方面后面的查询,分析。
日志格式
不管是web日志,还是应用日志,最好有一个比较统一的格式(例如时间格式),方面日志的查询,入库,和分析。还有一些应用统一使用json的日志格式,也挺好的。
不好的做法
- 日志中含有用户敏感信息
- 线上程序中使用 print
- 生产环境使用 debug 级别日志 ��
日志切分
日志可以按照每天,每周或者是文件的大小,切分之后压缩。一方面容易按时间回溯,另一方面可以减少磁盘空间,对于很久之前的日志,可以传输到远程服务器,或者是删除。
Python 日志
好习惯
- root级别的设置: 日志格式, 有利于标准化
- class 中设置logger
self.logger = logging.getLogger(type(self).__name__)
- 模块,文件中设置 logger
logger = logging.getLogger(__name__)
- 使用JSON YAML等格式来配置logging,感觉比使用代码或者 ini格式看起来更方面
- 错误日志是比较特殊的日志,因为它需要更多的信息,例如错误产生的上下文,还有错误堆栈等信息。可以通过
python logging context pypi
关键词google一些信息,或者自己设计一个 logging handler 来实现。
实际问题
- 简单的小应用中,单个日志文件,同时还要打印控制台
import logginglogging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M', filename='/temp/myapp.log', filemode='w')console = logging.StreamHandler()console.setLevel(logging.INFO)formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')console.setFormatter(formatter)# add the handler to the root loggerlogging.getLogger('').addHandler(console)
- 记录 Exception 的trace 信息(很有用哦)
try: open('/path/to/does/not/exist', 'rb')except (SystemExit, KeyboardInterrupt): raiseexcept Exception, e: logger.error('Failed to open file', exc_info=True)
- ini 格式例子
这里用了第三方的一个handler,ConcurrentRotatingFileHandler, 实现多进程安全
[loggers]keys=root[handlers]keys=stream, rotatingFile, errorFile[formatters]keys=form01[logger_root]level=DEBUGhandlers=stream, rotatingFile, errorFile[handler_stream]class=StreamHandlerlevel=NOTSETformatter=form01args=(sys.stdout,)[handler_errorFile]class=FileHandlerlevel=ERRORformatter=form01args=('./logs/portal.log', 'a')[handler_rotatingFile]level=INFOformatter=form01class=handlers.ConcurrentRotatingFileHandlerargs=('./logs/portal.log','a',50240000, 10)[formatter_form01]format=%(asctime)s %(name)s %(levelname)s %(message)sdatefmt=class=logging.Formatter
引用
import loggingimport logging.configimport cloghandlerlogging.config.fileConfig(join(BASE_DIR, "conf/log.conf"))logger = logging.getLogger(__name__)
默认会使用 root 这个logger,如果名称匹配就使用对应的logger。 一个logger也可以指定多个 handdler, 用来处理不同的日志级别等。
- JSON格式 例子
配置
{ "version": 1, "disable_existing_loggers": false, "formatters": { "simple": { "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" } }, "handlers": { "console": { "class": "logging.StreamHandler", "level": "DEBUG", "formatter": "simple", "stream": "ext://sys.stdout" }, "info_file_handler": { "class": "logging.handlers.RotatingFileHandler", "level": "INFO", "formatter": "simple", "filename": "info.log", "maxBytes": 10485760, "backupCount": 20, "encoding": "utf8" }, "error_file_handler": { "class": "logging.handlers.RotatingFileHandler", "level": "ERROR", "formatter": "simple", "filename": "errors.log", "maxBytes": 10485760, "backupCount": 20, "encoding": "utf8" } }, "loggers": { "my_module": { "level": "ERROR", "handlers": ["console"], "propagate": "no" } }, "root": { "level": "INFO", "handlers": ["console", "info_file_handler", "error_file_handler"] }}
获取配置
import osimport jsonimport logging.configdef setup_logging( default_path='logging.json', default_level=logging.INFO, env_key='LOG_CFG'): """Setup logging configuration """ path = default_path value = os.getenv(env_key, None) if value: path = value if os.path.exists(path): with open(path, 'rt') as f: config = json.load(f) logging.config.dictConfig(config) else: logging.basicConfig(level=default_level)
- 把日志格式化成json的工具
python-json-logger,logmatic json-logger增加的一些封装
import logging.handlersfrom pythonjsonlogger import jsonloggerimport datetimeclass JsonFormatter(jsonlogger.JsonFormatter, object): def __init__(self, fmt="%(asctime) %(name) %(processName) %(filename) %(funcName) %(levelname) %(lineno) %(module) %(threadName) %(message)", datefmt="%Y-%m-%dT%H:%M:%SZ%z", style='%', extra={}, *args, **kwargs): self._extra = extra jsonlogger.JsonFormatter.__init__(self, fmt=fmt, datefmt=datefmt, *args, **kwargs) def process_log_record(self, log_record): # Enforce the presence of a timestamp if "asctime" in log_record: log_record["timestamp"] = log_record["asctime"] else: log_record["timestamp"] = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ%z") if self._extra is not None: for key, value in self._extra.items(): log_record[key] = value return super(JsonFormatter, self).process_log_record(log_record)
参考
- Logging Cookbook 文档一定是要看的
- 日志最佳实践
- good-logging-practice-in-python
- Sentry 日志收集,分析系统,基于Python
- ConcurrentLogHandler 解决多进程日志同步问题
0 0
- Python logging 模块和使用经验
- 使用python的logging模块
- 使用python的logging模块
- 使用python的logging模块
- 使用python的logging模块
- 使用python的logging模块
- 使用python的logging模块
- 使用python的logging模块
- Python笔记:logging模块使用
- 使用python的logging模块
- python logging模块使用教程
- 【python】logging模块的使用
- 使用python的logging模块
- python模块 ---logging模块
- logging in python: logging模块的简单使用
- [Python学习] Logging模块的简单使用
- [Python学习]Logging模块的简单使用
- python的日志logging模块使用总结
- Android 百度在线语音识别
- 揭露:内江苏家桥医院怎么骗钱
- 远古流媒体技术在视频新闻中的应用
- 得到file文件内容
- 配置ssh免密码登录
- Python logging 模块和使用经验
- LeetCode OJ-11.Container With Most Water
- Spring内部方法性能监控器
- Oracle ORA-26085:直接路径操作必须启动它自己的事务处理
- C++项目目录组织结构
- 初始化bool(布尔)数组为false
- Spring基于XML和annotation的配置
- 【Android】这些ADB常用命令你都知道么?
- 封装ZIP包下载文件excel