python logging 最佳实践

起因

我经常跟同事开玩笑,我说在一家公司里面,能把日志这个功能搞清楚的都没有几个。所以写篇文章把我知道的部分知识分享一下。
在我目前看到的日志的文档中,Python的官方的文章是最清晰明了,推荐大家都来阅读下
https://docs.python.org/2/howto/logging.html

这个流程图非常重要,希望朋友们能仔细看看。
这里写图片描述

1. 适用场景

1.1 一般场景

在一般情况下,我们最常用的的handler有两个:

  • RotatingFileHandler
    按设定的文件大小切分日志
  • TimedRotatingFileHandler
    按时间切分日志
    以上2个handler都是线程安全的,可以用于多线程的场景,对于多进程则需要考虑其它方法
1.2 多进程

对于多进程的场景,python官方文档推荐我们使用

在单机上,即日志发送client 和 日志收集server 在同一台机器上,压测结果

typerecord/second
TCP6000
UDP9000

除此之外还可以考虑一下两种方法:
1. python-logstash
使用logstash,打开logstash的UDP或者TCP的服务端口直接接受数据,收到的数据可以入ElasticSearch 或者直接输出到文件中
2. 自定义新的handler 将日志记录存入redis 的某个队列中,再额外启动一个进程,从redis中把数据读出入到文件中

2. 日志的级别

LevelNumeric value
CRITICAL50
ERROR40
WARNING30
INFO20
DEBUG10
NOTSET0

一般情况下日志文件只需要分成两个即可
1. all.log
存储 >= INFO 级别的日志
测试环境可以开到DEBUG 级别
可以跟踪业务流程等等
2. error.log
存储 >= ERROR 级别的日志
便于快速排查故障

一个常见的日志初始化模块可以这样书写
logger_helper.py

import logging
import sys
import time
from logging import Logger
from logging.handlers import TimedRotatingFileHandler

def init_logger(logger_name):
    if logger_name not in Logger.manager.loggerDict:
        logger = logging.getLogger(logger_name)
        logger.setLevel(logging.DEBUG)
        # handler all
        handler = TimedRotatingFileHandler('./all.log', when='midnight',backupCount=7)
        datefmt = "%Y-%m-%d %H:%M:%S"
        format_str = "[%(asctime)s]: %(name)s %(levelname)s %(lineno)s %(message)s"
        formatter = logging.Formatter(format_str, datefmt)
        handler.setFormatter(formatter)
        handler.setLevel(logging.INFO)
        logger.addHandler(handler)
        # handler error
        handler = TimedRotatingFileHandler('./error.log', when='midnight',backupCount=7)
        datefmt = "%Y-%m-%d %H:%M:%S"
        format_str = "[%(asctime)s]: %(name)s %(levelname)s %(lineno)s %(message)s"
        formatter = logging.Formatter(format_str, datefmt)
        handler.setFormatter(formatter)
        handler.setLevel(logging.ERROR)
        logger.addHandler(handler)


    logger = logging.getLogger(logger_name)
    return logger

logger = init_logger("dataservice")


if __name__ == '__main__':
    logger = init_logger('dataservice')
    logger.error("test-error")
    logger.info("test-info")
    logger.warn("test-warn")

只需要在其它模块中引入此模块的logger即可
model.py

from logger_helper import logger

def business_code():
        # ... ...
        logger.info("...")
# call business code
business_code()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值