django日志分割的几种处理

文章目录

      • 一、按日志大小分割
          • 1、使用RotatingFileHandler 日志日志处理器
      • 二、按日期分割
          • 1、通过TimedRotatingFileHandler 日志处理器实现
      • 三、多进程情况下补充
        • 解决方案:
          • 1、使用concurrent-log-handler 三方包中的ConcurrentRotatingFileHandler处理器
          • 2、重写logging.handlers.TimedRotatingFileHandler实现多进程日期分割

一、按日志大小分割

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):@propertydef dfn(self):currentTime = int(time.time())# get the time that this sequence started at and make it a TimeTupledstNow = time.localtime(currentTime)[-1]t = self.rolloverAt - self.intervalif self.utc:timeTuple = time.gmtime(t)else:timeTuple = time.localtime(t)dstThen = timeTuple[-1]if dstNow != dstThen:if dstNow:addend = 3600else:addend = -3600timeTuple = time.localtime(t + addend)dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple))return dfndef shouldRollover(self, record):"""是否应该执行日志滚动操作:1、存档文件已存在时,执行滚动操作2、当前时间 >= 滚动时间点时,执行滚动操作"""dfn = self.dfnt = int(time.time())if t >= self.rolloverAt or os.path.exists(dfn):return 1return 0def 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 TimeTupledfn = 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 houraddend = -3600else:           # DST bows out before next rollover, so we need to add an houraddend = 3600newRolloverAt += addendself.rolloverAt = newRolloverAt

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


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部