python日志管理

logging

简介

日志级别等级排序:critical > error > warning > info > debug
级别越高打印的日志越少,反之亦然,即

  • debug : 打印全部的日志( notset 等同于 debug )
  • info : 打印 info, warning, error, critical 级别的日志
  • warning : 打印 warning, error, critical 级别的日志
  • error : 打印 error, critical 级别的日志
  • critical : 打印 critical 级别
通过 logging.basicConfig() 可以设置 root 的日志级别,和日志输出格式。
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p',level=logging.DEBUG)

logging 模块四大组件

日志器(logger)需要通过处理器(handler)将日志信息输出到目标位置,不同的处理器(handler)可以将日志输出到不同的位置;
日志器(logger)可以设置多个处理器(handler)将同一条日志记录输出到不同的位置;
每个处理器(handler)都可以设置自己的过滤器(filter)实现日志过滤,从而只保留感兴趣的日志;
每个处理器(handler)都可以设置自己的格式器(formatter)实现同一条日志以不同的格式输出到不同的地方。

日志器(logger)是入口,真正干活儿的是处理器(handler),处理器(handler)还可以通过过滤器(filter)和格式器(formatter)对要输出的日志内容做过滤和格式化等处理操作。

Logger 可以包含一个或多个 Handler 和 Filter
Logger 与 Handler 或 Fitler 是一对多的关系
一个 Logger 实例可以新增多 个 Handler,一个 Handler 可以新增多个格式化器或多个过滤器,而且日志级别将会继承。
  1. 日志器- Logger
  • 日志记录器不直接实例化,而是通过模块级函数 logger.getlogger (name) 来实例化
  • 创建方法: logger = logging.getLogger(模块块儿名)
  • logger.setLevel(logging.ERROR) # 设置日志级别为 ERROR,即只有日志级别大于等于 ERROR 的日志才会输出
  • logger.addHandler(handler_name) # 为 Logger 实例增加一个处理器
  • logger.removeHandler(handler_name) # 为 Logger 实例删除一个处理器
  1. 处理器- Handler
  • 很多种,常用:StreamHandler,FileHandler,NullHandler
  • 创建方法:sh = logging.StreamHandler(stream=None)
  • ch.setLevel(logging.WARN) # 指定日志级别,低于WARN级别的日志将被忽略
  • ch.setFormatter(formatter_name) # 设置一个格式化器formatter
  • ch.addFilter(filter_name) # 增加一个过滤器,可以增加多个
  • ch.removeFilter(filter_name) # 删除一个过滤器
  1. 过滤器- Filter
  • 创建方法: filter = logging.Filter(name=‘’)
  1. 格式器- Formatter
  • 创建方法: formatter = logging.Formatter(fmt=None, datefmt=None)
logging标准模块支持三种配置方式: dictConfig,fileConfig,listen。字典配置、文件配置、显式配置

应用

一、
logging.conf

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
import logging
import logging.config

logging.config.fileConfig('logging.conf')

# create logger
logger = logging.getLogger('simpleExample')

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

二、

import logging
from logging.handlers import TimedRotatingFileHandler

class MylogHandler(logging.Logger):
    def __init__(self,name,level="DEBUG",stream=True,files=True):
        self.name = name
        self.level = level
        logging.Logger.__init__(self,self.name,level=self.level)
        if stream:
            self.__streamHandler__(self.level)
        if files:
            self.__filesHandler__(self.level)
    
    def __streamHandler__(self,level=None):
        handler = TimedRotatingFileHandler(filename=self.name+".log", when='D', interval=1, backupCount=15)
        handler.suffix = '%Y%m%d.log'
        handler.setLevel(level)
        formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
        
        handler.setFormatter(formatter)

        self.addHandler(handler) #将hander添加到logger上
        
    def __filesHandler__(self,level=None):
        handler = logging.StreamHandler()
        formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
        handler.setFormatter(formatter)
        handler.setLevel(level)
        self.addHandler(handler)
        
    
if __name__ == '__main__':
    log = MylogHandler('test')
    log.info('this is a my log handler')

三、

import os
import sys
import re
import logging
from logging import handlers

__all__ = ['Logger']


class Logger(object):
    # 日志级别关系映射
    DEFAULT_FMT = '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
    LEVEL_DICT = {
        'debug': logging.DEBUG,
        'info': logging.INFO,
        'warning': logging.WARNING,
        'error': logging.ERROR,
        'critical': logging.CRITICAL
    }

    def __init__(
            self,
            log_obj,
            filename,
            level='info',
            when='s',
            backupCount=3,
            fmt=DEFAULT_FMT
    ):
        self.logger = logging.getLogger(log_obj)
        self.fmt = logging.Formatter(fmt)
        self.setLogDir(filename)
        self.logger.setLevel(self.LEVEL_DICT.get(level))  # level
        # self.logger.addHandler(self.setStream(self.fmt))
        self.logger.addHandler(self.setTimeRotator(
            filename=filename,
            when=when,
            backupCount=backupCount
        ))
        # self.logger.addHandler(self.setEmailHandler())

    def setLogDir(self, filename):
        _dir, _ = os.path.split(filename)
        if not os.path.exists(_dir):
            os.makedirs(_dir)

    # System standard output
    def setStream(self, fmt=None):

        handler = logging.StreamHandler(sys.stdout)

        if not fmt:
            handler.setFormatter(fmt)
        else:
            handler.setFormatter(self.fmt)
        return handler

    # Log record settings, include writing file, backup, etc.

    @classmethod
    def setTimeRotator(cls, filename, when, backupCount, encoding='utf-8', level=None, **kwargs):
        handler = handlers.TimedRotatingFileHandler(
            filename=filename,
            when=when,
            backupCount=backupCount,
            encoding=encoding,
            **kwargs
        )

        # Warnings: suffix issue is a `logging` package bug.
        # Must add `.log` string to `suffix` attribute format,
        # Or `TimedRotatingFileHandler` can't backup log files.
        # Specific formatting can be read in `logging.TimedRotatingFileHandler`
        if level is None:
            handler.setLevel(cls.LEVEL_DICT.get('info'))
        else:
            handler.setLevel(level)
        handler.suffix = "%Y-%m-%d_%H-%M-%S.log"
        handler.extMatch = re.compile(r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(\.\w+)?$")
        handler.setFormatter(logging.Formatter(cls.DEFAULT_FMT))  # 设置文件里写入的格式
        return handler

    # TODO: email handler.
    def setEmailHandler(self, mailhost, fromaddr, toaddrs, subject,
                        credentials=None, secure=None, timeout=5.0, level='info'):
        email = handlers.SMTPHandler(
            mailhost,
            fromaddr,
            toaddrs,
            subject,
            credentials=None,
            secure=None,
            timeout=5.0
        )

        email.setLevel(self.LEVEL_DICT.get('error'))
        email.setFormatter(logging.Formatter(
            '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'))
        return email

四、

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '[%(asctime)s] [%(levelname)s] %(message)s'
        },
    },
    'handlers': {
        # 输出日志的控制台
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        },
        # 输出日志到文件,按日期滚动
        'file': {
            'level': 'DEBUG',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            # TimedRotatingFileHandler的参数
            # 参照https://docs.python.org/3/library/logging.handlers.html#timedrotatingfilehandler
            # 目前设定每天一个日志文件
            'filename': 'logs/all_info.log',
            'when': 'midnight',
            'interval': 1,
            'backupCount': 100,
            'formatter': 'verbose'
        },
        # 发送邮件,目前腾讯云、阿里云的服务器对外发送邮件都有限制,暂时不使用
        'email': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'include_html': True,
        }
    },
    'loggers': {
        # 不同的logger
        'django': {
            'handlers': ['console', 'file'],
            'level': 'INFO',
            'propagate': True,
        },
    },
}


logger = logging.getLogger('django')  # 日志捕捉方法
logging.config.dictConfig(settings.LOGGING)

logger.error(e.__class__.__name__)
logger.error('视图报错,报错详情如下:\n%s' % traceback.format_exc())  # todo 显示报错第几行

loguru

  • 配置
from loguru import logger
logger.add('file_{time}.log', format="{name} {level} {message}", level="INFO", rotation='5 MB', encoding='utf-8', , rotation="1 week", compression="zip"))  
# 根据时间为日志命名,每5MB新建一个, 一周清理一次,压缩节省空间

logger.add('out.log', backtrace=True, diagnose=True, encoding='utf-8')
完整描述异常:包括内存地址,可能泄露敏感数据

logger.add('json.log', serialize=True, encoding='utf-8') #保存为json格式日志
  • 使用
# 装饰器
from loguru import logger
@logger.catch
def func(x, y, z):
    return 1 / (x + y + z)

# 上下文
with logger.catch():
    func(0, 1, -1)
from loguru import logger
from utils.path_config import ConfigFilePath


class DWLog(object):
    def __init__(self, module):
        self.module = module
        self.log_obj = logger
        self.log_obj.add(ConfigFilePath().log_file(self.module), format="{time} | {message}",
                         rotation="20 MB", encoding='utf-8', retention="30 days",
                         enqueue=True)
        # self.log_obj.add(ConfigFilePath().log_file("error"), format="{time} | {message}",
        #                  rotation="20 MB", encoding='utf-8', retention="30 days", level='ERROR', enqueue=True)

    def log(self, msg):
        self.log_obj.info("[%s]--%s" % (self.module, msg))


_ = DWLog('hot')
log, logger = _.log, _.log_obj  # 打印和保存log,catch 异常
log("hot_word_trend ok")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值