背景
日常使用的是concurrent-log來列印Python專案的日志,該庫是基于原生logging庫的二次開發,以支持多行程日志列印,但有個不滿意的地方就是日志檔案的后綴是日期結尾(當然可能有其他方式可以設定,但我沒有找到),不管如何能解決自己的需求就行,程序不重要
修改前log檔案

解決辦法
對ConcurrentTimedRotatingFileHandler類下的doRollover方法重寫
class PrivateConcurrentTimedRotatingFileHandler(ConcurrentTimedRotatingFileHandler):
# 重寫doRollover方法,用于支撐日志翻轉的檔案命名
def doRollover(self):
"""
本方法繼承Python標準庫,修改的部分已在下方使用注釋標記出
"""
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)
# 每天生成的日志檔案沒有后綴,需要修改原始碼:TimedRotatingFileHandler類下的doRollover方法-->
# dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple)后面拼接后綴名
# dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple) + ".log")
dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple) + ".log")
"""
如果翻轉檔案已經生成,則說明其他行程已經處理過翻轉
處理日志檔案已經翻轉當前行程中未寫入檔案的日志副本,修改開始
"""
# 直接修改靜態變數,因為代碼執行到此處已經獲取到非重入行程鎖,保證同一時間只有一個執行緒對變數進行修改
# 由于Python GIL,同一時間同一行程內只有一個執行緒運行,執行緒切換后快取自動失效,即其他執行緒可以看見修改后的最新值
# 記錄每一次觸發翻轉動作的時間,不管反轉是否真的執行
ConcurrentTimedRotatingFileHandler.before_rollover_at = self.rolloverAt
if os.path.exists(dfn):
# 因為行程變數不會在記憶體同步,所以存在其他行程已經翻轉過日志檔案當時當前行程中還標識為未翻轉
# 日志內容創建時間如果小于等于下一個處理翻轉時刻,則將日志寫入反轉后的日志檔案,而不是當前的baseFilename
# 當前磁盤上的baseFilename對于當前行程中的標識副本來說已經是翻轉后要寫入的檔案
# 所以當檔案存在時,本次不再進行翻轉動作
pass
else:
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()
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
重寫后,呼叫自己的子類PrivateConcurrentTimedRotatingFileHandler即可
def get_logger(self):
"""在logger中添加日志句柄并回傳,如果logger已有句柄,則直接回傳
我們這里添加兩個句柄,一個輸出日志到控制臺,另一個輸出到日志檔案,
兩個句柄的日志級別不同,在組態檔中可設定,
"""
if not self.logger.handlers: # 避免重復日志
console_handler = logging.StreamHandler()
console_handler.setFormatter(self.formatter)
console_handler.setLevel(self.console_output_level)
self.logger.addHandler(console_handler)
# 每天重新創建一個日志檔案,最多保留backup_count份
# 每天生成的日志檔案沒有后綴,需要修改原始碼:TimedRotatingFileHandler類下的doRollover方法-->
# dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple)后面拼接后綴名
# dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple) + ".log")
file_handler = PrivateConcurrentTimedRotatingFileHandler(filename=os.path.join(self.log_path, self.log_file_name),
when='MIDNIGHT',
interval=1,
backupCount=self.backup_count,
delay=True,
encoding='utf-8'
)
file_handler.setFormatter(self.formatter)
file_handler.setLevel(self.file_output_level)
self.logger.addHandler(file_handler)
修改后log檔案

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/231335.html
標籤:其他
上一篇:Python專案多行程列印日志
下一篇:Python ES日志庫CMRESHandler修復[[types removal] Specifying types in bulk requests is deprecated.]警告
