快速實現Python多程序logging日誌按天切割
前幾天填了一個前人留下的“日誌”坑,程式日誌只有程式重啟才可以生成一個新日誌檔案,這樣就會導致程式長時間執行之後,會生成一個巨大的日誌檔案,不方便後期問題查詢或磁碟清理,所以日誌按天切割勢在必行。
python 原生logging日誌模組可以滿足大部分需求,但是唯獨不適合多程序下日誌切割,具體的原因可以自行百度一下,網上有很多講解的,我就說一下,如何用最小的改動logging原始碼的方法來實現pyhon多程序下日誌按天(分鐘、小時)切割。
直接上程式碼:
1、修改logging模組中的TimedRotatingFileHandler(BaseRotatingHandler)類方法doRollover(self):
class TimedRotatingFileHandler(BaseRotatingHandler):
def doRollover(self):
"""
do a rollover; in this case, a date/time stamp is appended to the filename
when the rollover happens. However, you want the file to be named for the
start of the interval, not the current time. If there is a backup count,
then we have to get a list of matching filenames, sort them and remove
the one with the oldest suffix.
"""
if self.stream:
self.stream.close()
self.stream = None
# get the time that this sequence started at and make it a TimeTuple
currentTime = int(time.time())
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.baseFilename + "." + time.strftime(self.suffix, timeTuple)
self.baseFilename = self.baseFilename.split('.log')[0] + '.log-' + time.strftime('%Y%m%d',time.localtime(time.time()))
(新增一條語句)
''' 原始碼註釋部分,其他的不需要改動
if os.path.exists(dfn):
os.remove(dfn)
os.rename(self.baseFilename, dfn)
'''
os.remove(dfn)
os.rename(self.baseFilename, dfn)
'''
if self.backupCount > 0:
# find the oldest log file and delete it
#s = glob.glob(self.baseFilename + ".20*")
#if len(s) > self.backupCount:
# s.sort()
# os.remove(s[0])
for s in self.getFilesToDelete():
os.remove(s)
#print "%s -> %s" % (self.baseFilename, dfn)
self.stream = self._open()
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]
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
2、寫了一個通用模組,方便以後去呼叫 log.py
# -*- coding: UTF8 -*-
#!/usr/bin/python
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import logging, logging.handlers
import time
import os
filePath = os.path.split(os.path.realpath(__file__))[0].replace("common", "logs")
def set_log(shellname):
filename = filePath + '/' + shellname.replace('.log','') + '.log-' + time.strftime('%Y%m%d',time.localtime(time.time()))
print filename
fmt_str = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s'
fileshandle = logging.handlers.TimedRotatingFileHandler(filename, when='M', interval=1, backupCount=0)
fileshandle.suffix = "%Y%m%d_%H%M%S.log"
fileshandle.setLevel(logging.DEBUG)
formatter = logging.Formatter(fmt_str)
fileshandle.setFormatter(formatter)
logger = logging.getLogger('')
logger.setLevel(logging.INFO)
logger.addHandler(fileshandle)
3、呼叫模組方法:
import log
log.set_log("ReceiveCustomerDetailForHashtable_")
log.logging.error(".....")
4、自此就實現的python多程序按天切割日誌。
實現原理:利用logging模組自帶的按時間自定義切割日誌模組,稍加修改一下,就可以實現。
但是就是有一個坑:日誌生成格式是固定的,要麼是按天或按小時或按分鐘生成
不過日誌切割一般都不會發生變化,所以這個坑還可以接受,或者分享一下,你自己的好方法。