TimedRotatingFileHandlerのログローテーション
RHEL6やCentOS6で標準のPythonのバージョンは2.6なのでPython2.6を使うことがあるのですが、2.7以降では見られない挙動がありました。
from logging import getLogger
from logging.handlers import TimedRotatingFileHandler
logger = getLogger(__name__)
handler = TimedRotatingFileHandler("hoge.log",'S')
logger.addHandler(handler)
logger.error("test")
上記のようなファイルを作って実行すると、Python2.7以降(3系含む)ならログローテートされてhoge.log.2018-01-31_02-04-27
といったファイルが作られるかと思います。
しかし、Python2.6だとログローテートされずにhoge.log
に追記され続けてしまいます。
ログローテートされない原因
原因を探ろうと公式サイトからソースコードを取ってみたら、TimedRotatingFileHandler
クラスのコンストラクタで設定されるrolloverAt
の値に違いが有りました。
class TimedRotatingFileHandler(BaseRotatingHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0):
# 略
self.rolloverAt = self.computeRollover(int(time.time()))
class TimedRotatingFileHandler(BaseRotatingHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0):
# 略
if os.path.exists(filename):
t = os.stat(filename)[ST_MTIME]
else:
t = int(time.time())
self.rolloverAt = self.computeRollover(t)
computeRollover
は次にログローテートが必要な時刻を計算するメソッドです。
計算は引数の時刻にもとづいて行われます。
when="S",interval=5"
ならt
の5秒後、when="D",interval=5"
ならt
の5日後、when="MIDNIGHT"
ならt
の次の00:00、というように動作します。
2.6ではt
の値がスクリプトを実行された時刻となるため、ログローテートする時間に達することがなかったということになります。
つまり、下記のようにsleepを入れるとログローテートしてくれそうです。
from logging import getLogger
from logging.handlers import TimedRotatingFileHandler
from time import sleep
logger = getLogger(__name__)
handler = TimedRotatingFileHandler("hoge.log",'S')
logger.addHandler(handler)
sleep(2)
logger.error("test")
解決策
1日毎にログローテートするために24時間sleepを入れるのは現実的ではないので、Python2.7のコードを移植したいと思います。
クラスを作らなくても直接書いても良い気もします。
from logging import getLogger
from logging.handlers import TimedRotatingFileHandler
from time import sleep
from stat import ST_MTIME
import os
class TimedRotatingFileHandler26(TimedRotatingFileHandler):
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=0, utc=0):
super().__init__(filename, when, interval, backupCount, encoding, delay, utc)
if os.path.exists(filename):
t = os.stat(filename)[ST_MTIME]
self.rolloverAt = self.computeRollover(t)
logger = getLogger(__name__)
handler = TimedRotatingFileHandler26("hoge.log",'S')
logger.addHandler(handler)
logger.error("test")
これでPython2.6でもログローテートするようになるかと思います。