使用TimedRotatingFileHandler并按小时翻转时,这个python日志模块是否会出错?

时间:2016-03-01 11:44:01

标签: python python-2.7 logging

使用python日志记录模块类TimedRotatingFileHandler。课程检查应在下面使用翻转,

def shouldRollover(self, record):
    t = int(time.time())
    if t >= self.rolloverAt:
        return 1
    return 0

并使用

计算下一个翻转时间
def doRollover(self): 
    currentTime = int(time.time())
    newRolloverAt = self.computeRollover(currentTime)
    self.rolloverAt = newRolloverAt
def computeRollover(self, currentTime):
    result = currentTime + self.interval

例如,如果流程在2016/03/01 19:33:00开始,则self.rolloverAt首先设置为2016/03/01 20:00:00,但在2016/03年之前可能无法写入/ 01 20:00:05,所以第一次翻转将在20:00:05发生,并将newRolloverAt设置为2016/03/01 21:00:05,然后下一次全部翻转将不会在一个开始时发生小时。

2 个答案:

答案 0 :(得分:3)

不,这不是错误。这是设计的。如果您从开始时间开始遵循确切的时间间隔,则最终可能会出现不稳定的翻转。如果您的应用程序在下一个“固定”翻转时间前不久安静,您将得到两个新文件紧密相关(例如,一小时前5秒,下一小时创建)。

因此,对于区间类型SMHD,稀疏日志记录将导致在下一个日志条目进入时开始的新间隔。在下次轮换之前你仍然可以获得一个完整的持续时间。

midnightW0 .. W6工作日轮换的例外情况;在您找到的代码的正下方,可以为下一次翻转进行下一个午夜(如果需要,正确的工作日)的精确计算。那是因为这些间隔意味着当天的特定时间。使用整天进行日志记录,旋转点之前的最后一分钟日志条目远不是问题。

答案 1 :(得分:1)

Realy来自日志记录API的TimedRotatingFileHandler不支持您(以及我)所期望的行为。 我看到了消息来源,我猜这是糟糕的设计,然后很难在没有解决方法的情况下调整行为。 在Java中,log4j支持这种行为没有问题,直到现在我找不到另外的Python API。

但我做了一个解决方法类,就像TimeBasedTriggeringPolicy中的log4j一样:

from logging.handlers import TimedRotatingFileHandler

class SyncTimedRotatingFileHandler(TimedRotatingFileHandler):
    def __init__(self, filename, when='h', backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
        TimedRotatingFileHandler.__init__(self, filename, when=when, interval=1, backupCount=backupCount, encoding=encoding, delay=delay, utc=utc, atTime=atTime)    

    def computeRollover(self, currentTime):
        currentTime = currentTime if (self.when == 'MIDNIGHT' or self.when.startswith('W')) else currentTime - (int(currentTime) % self.interval)
        return TimedRotatingFileHandler.computeRollover(self, currentTime)

并测试:

logger = logging.Logger('myLogger')
handler = SyncTimedRotatingFileHandler('synctime.log', 'M', 0, 'UTF-8', False, False, None)
formatter = logging.Formatter('%(asctime)s %(message)s')
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
logger.addHandler(handler)
c = 0
while (True):
  c += 1
  logger.info("Logger Test " + str(c))
  time.sleep(1)