django日志分割的几种处理

一、按日志大小分割

1、使用RotatingFileHandler 日志日志处理器
  • 需配置maxBytes与backupCount参数,不为0时生效

说明:log文件大小接近maxBytes时,新建一个文件作为log的输出,旧的文件会被加上类似’.1’、’.2’的后缀。 举个例子,如果backupCount=5,log file定义的名字为app.log,你会得到app.log, app.log.1, app.log.2 一直到 app.log.5。 然而被写入日志的永远是app.log,写满了之后重命名为app.log.1,如果app.log.1存在,app.log.1会先被重名名为app.log.2,依此类推。 另外,如果app.log.5存在,它会被删除。


# settings配置
'handlers': {
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'default': {                                            # 用于文件输出
            'level': 'INFO',                                    # 输出日志等级
            'class': 'logging.handlers.RotatingFileHandler',    # 日志类型
            'filename': '%s/django.log' % LOGGING_DIR,          # 具体日志文件的名字
            'maxBytes': 1024 * 1024 * 300,                        # 日志大小 300M
            'backupCount': 5,                                   # 备份数量  5个
            'formatter':'standard',                             # 输出日志格式
            'encoding': 'utf-8',                                # 输出日志编码
        }

二、按日期分割

1、通过TimedRotatingFileHandler 日志处理器实现
        'file': {
            'level': 'INFO',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename':  '%s/django.log' % LOGGING_DIR,     # 日志的文件名
            # TimedRotatingFileHandler的参数
            # 目前设定每天一个日志文件
            # 'S'         |  秒
            # 'M'         |  分
            # 'H'         |  时
            # 'D'         |  天
            # 'W0'-'W6'   |  周一至周日
            # 'midnight'  |  每天的凌晨
            'when': 'midnight',                             # 间间隔的类型
            'interval': 1,                                  # 时间间隔
            'backupCount': 100,                             # 能留几个日志文件;过数量就会丢弃掉老的日志文件
            'formatter': 'standard',                        # 日志文本格式
            'encoding': 'utf-8',                            # 日志文本编码
        },

三、多进程情况下补充

RotatingFileHandler 和 TimedRotatingFileHandler在多进程环境下会出现异常

1)异常情况如下:

  • 日志写入错乱;
  • 日志并没有按天分割,而且还会丢失。

2)出现异常的原因为:

  • Django logging 是基于 Python logging 模块实现的,logging 模块是线程安全的,但不能保证多进程安全。
  • 多进程日志操作时,句柄操作可能混乱;一个进程在做读写操作时,文件可能被另一进程执行删除重名操作
解决方案:
1、使用concurrent-log-handler 三方包中的ConcurrentRotatingFileHandler处理器
  • pip install concurrent-log-handler
# settings.py
LOGGING = {
    ...
    'handlers': {
        ...
        'file': {
            'level': 'INFO',
            'class': 'concurrent_log_handler.ConcurrentRotatingFileHandler',
            'filename': os.path.join(LOGS_DIR, 'app.log'),
            'formatter': 'verbose',
            'maxBytes': 1024,
            'backupCount': 5
        },
        ...
    }
    ...
}

缺点:

  • 仅支持文件大小分割,不支持日期分割
2、重写logging.handlers.TimedRotatingFileHandler实现多进程日期分割

重写原理:

  • 去掉删文件的逻辑
  • 在切割文件时,及时将写入句柄更新到最新。
import os
import time
from logging.handlers import TimedRotatingFileHandler
class CommonTimedRotatingFileHandler(TimedRotatingFileHandler):
    @property
    def dfn(self):
        currentTime = int(time.time())
        # get the time that this sequence started at and make it a TimeTuple
        dstNow = time.localtime(currentTime)[-1]
        t = self.rolloverAt - self.interval
        if self.utc:
            timeTuple = time.gmtime(t)
        else:
            timeTuple = time.localtime(t)
            dstThen = timeTuple[-1]
            if dstNow != dstThen:
                if dstNow:
                    addend = 3600
                else:
                    addend = -3600
                timeTuple = time.localtime(t + addend)
        dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple))
        return dfn
    def shouldRollover(self, record):
        """
        是否应该执行日志滚动操作:
        1、存档文件已存在时,执行滚动操作
        2、当前时间 >= 滚动时间点时,执行滚动操作
        """
        dfn = self.dfn
        t = int(time.time())
        if t >= self.rolloverAt or os.path.exists(dfn):
            return 1
        return 0
    def doRollover(self):
        """
        执行滚动操作
        1、文件句柄更新
        2、存在文件处理
        3、备份数处理
        4、下次滚动时间点更新
        """
        if self.stream:
            self.stream.close()
            self.stream = None
        # get the time that this sequence started at and make it a TimeTuple
        dfn = self.dfn
        # 存档log 已存在处理
        if not os.path.exists(dfn):
            self.rotate(self.baseFilename, dfn)
        # 备份数控制
        if self.backupCount > 0:
            for s in self.getFilesToDelete():
                os.remove(s)
        # 延迟处理
        if not self.delay:
            self.stream = self._open()
        # 更新滚动时间点
        currentTime = int(time.time())
        newRolloverAt = self.computeRollover(currentTime)
        while newRolloverAt <= currentTime:
            newRolloverAt = newRolloverAt + self.interval
        # If DST changes and midnight or weekly rollover, adjust for this.
        if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc:
            dstAtRollover = time.localtime(newRolloverAt)[-1]
            dstNow = time.localtime(currentTime)[-1]
            if dstNow != dstAtRollover:
                if not dstNow:  # DST kicks in before next rollover, so we need to deduct an hour
                    addend = -3600
                else:           # DST bows out before next rollover, so we need to add an hour
                    addend = 3600
                newRolloverAt += addend
        self.rolloverAt = newRolloverAt

声明:本文引用自https://blog.csdn.net/TFATS/article/details/106408296 文章写的非常好,非常清晰

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值