Python计划日志轮换

时间:2016-04-20 16:06:29

标签: python logging rotation

编辑:

其他人看起来与TimedRotatingFileHandler有类似的问题。

Python TimedRotatingFileHandler not rotating at midnight till something new is written to the log file. How to fix this?

Why doesn't my TimedRotatingFileHandler rotate at midnight?

显然,除非日志中发生某些活动,否则日志不会旋转。有没有办法可以使用内置处理程序实现我想要的预定旋转功能而无需创建自定义旋转器?

原始邮件:

我正在使用Python logging模块的TimedRotatingFileHandler来定期轮换我的日志。

我已经在logging.conf中为我的应用程序的记录器和处理程序指定了配置:

[logger_worker]
level=DEBUG
propogate=0
qualname=worker
handlers=workerHandler

[handler_workerHandler]
class=handlers.TimedRotatingFileHandler
level=DEBUG
formatter=standardFormatter
args=("/var/log/app/worker.log","M",1,30,None,False,False)
  • 注意:出于测试目的,我已将处理程序配置为每分钟旋转日志,但理想情况下,日志将在午夜每天轮换。

在我的应用中,我正在创建这样的记录器:

logging.config.fileConfig("logging.conf")
log = logging.getLogger("worker")

log.debug('Hello world')

它没有像我预期的那样工作:

  1. 它没有旋转所有日志
  2. 由于配置为
  3. ,因此不会每分钟旋转一次

    观察日志目录的ls -l输出:

    -rw-r--r-- 1 root root       0 Apr 19 18:22 dpv.log
    -rw-r----- 1 root root    5092 Apr 20 11:47 emperor.log
    -rw-r--r-- 1 root root   88939 Apr 20 11:47 uwsgi.log
    -rw-r--r-- 1 root root     494 Apr 20 11:46 worker.log
    -rw-r--r-- 1 root root   45906 Apr 20 02:08 worker.log.2016-04-20_02-08
    -rw-r--r-- 1 root root     494 Apr 20 11:34 worker.log.2016-04-20_11-34
    -rw-r--r-- 1 root root     494 Apr 20 11:36 worker.log.2016-04-20_11-36
    -rw-r--r-- 1 root root     494 Apr 20 11:44 worker.log.2016-04-20_11-44
    

    我做错了什么?即使没有任何内容写入日志,是否可以在计划的期限内轮换日志?

2 个答案:

答案 0 :(得分:1)

似乎TimedRotatingFileHandler没有您需要的功能。 您可以尝试以下函数在特定时间旋转日志文件。

def log_rollover(folder_path):
    # folder_path: the absolute path to your log folder 
    today = str(datetime.date.today()).replace('-', '')
    list_of_files = os.listdir(folder_path)
    for log_file in list_of_files:
        file_path = folder_path + '/' + log_file
        if log_file.endswith('.log') and os.stat(file_path).st_size > 0:
            new_file_path = file_path.split('.')[-2] + '-' + today + '.log'
            subprocess.check_call(['cp', file_path, new_file_path])
            subprocess.check_call(['gzip', new_file_path])
            subprocess.check_call(['cp', '/dev/null', file_path]) 

此外,您还需要使用cron作业在特定时间运行该功能。 APScheduler可能是个不错的选择。例如,如果要在凌晨3点运行cron作业,可以使用:

folderPath = '/var/log/app'  # The path to your log folder
scheduler = BlockingScheduler()
scheduler.add_job(log_rollover, trigger='cron', args=[folderPath], hour=3, minute=0)
scheduler.start()

不要忘记为APScheduler设置时区。

答案 1 :(得分:1)

我遇到了同样的问题并想出了一个不同的方法:

from datetime import datetime
import os

def rotate_log_if_new_day(self):
    now = datetime.now().date()
    file_date = datetime.fromtimestamp(os.path.getmtime("manager.err")).date()
    if file_date != now:
        self.logger.debug("Date changed with no events - rotating the log...")
        self._errhandler.doRollover()
在经理的更新周期(每15分钟)调用

rotate_log_if_new_day(),以确保日志在午夜15分钟内轮换。如果日志已经旋转(即:记录了错误或已经进行了手动旋转),它什么都不做。

最初我有一个警卫阻止os.path...呼叫,除非日期已经改变,但是timeit()显示通过缓存当前日期(1.85μs对5.7μs)获得的微不足道的加速来验证没有动作必需的。