编辑:
其他人看起来与TimedRotatingFileHandler
有类似的问题。
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')
它没有像我预期的那样工作:
观察日志目录的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
我做错了什么?即使没有任何内容写入日志,是否可以在计划的期限内轮换日志?
答案 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)获得的微不足道的加速来验证没有动作必需的。