logging 時刻ローテーションファイル名の変更

Python の logging 、TimedRotatingFileHandler では、日替わりローテーションの場合、
ログファイル名=test.log に対して、
test.log.%Y-%m-%d
がデフォルトのローテーションファイル名である。
これを
 test_%Y-%m-%d.log
に変える方法は、、
handler の namer を以下のようにする。

handler.namer = lambda x: re.sub(r"\.([^.]+)\.(\d{4})-(\d{2})-(\d{2})$", r"_\2-\3-\4.\1", x)

でも、handler.extMatch で、ローテーションで削除する時の suffix とマッチするパターンを
変えれば対応できると思ったが、namer を変更した場合、削除対象とマッチするパターンを
うまく表現できなくなってしまう。→ いつまでもログが残ってしまう。

仕方ないので、Logger インスタンス生成時にローテーションで古くなるログファイルを
削除するようにする。

以下を差し込む。

from datetime import datetime, timedelta
import os

delfile = datetime.strftime((lambda x=datetime.now(): x - timedelta(days=7))(), '/var/log/test_%Y-%m-%d.log')
 if os.path.exists(delfile): os.remove(delfile)

最終的に logger.py を以下のようにする。

# -*- coding: UTF-8 -*-
from logging import Formatter, handlers, StreamHandler, getLogger, DEBUG, WARN, INFO
import inspect
import re
from datetime import datetime, timedelta
import os

class Logger:
    def __init__(self, name=__name__):
        if name=="blue.logger":
            fsplits = inspect.stack()[1].filename.split('/')
            name = fsplits[len(fsplits)-1]
        # ロガー生成
        self.logger = getLogger(name)
        self.logger.setLevel(DEBUG)
        formatter = Formatter(fmt="%(asctime)s.%(msecs)03d %(levelname)7s %(message)s [%(name)s  %(processName)s - %(threadName)s]",
                              datefmt="%Y/%m/%d %H:%M:%S")

        # 時刻ローテーション
        handler = handlers.TimedRotatingFileHandler(filename='/var/log/test.log',
                                                    encoding='UTF-8',
                                                    when='D',
                                                    backupCount=7 )
        handler.namer = lambda x: re.sub(r"\.([^.]+)\.(\d{4})-(\d{2})-(\d{2})$", r"_\2-\3-\4.\1", x)
        # old log delete
        delfile = datetime.strftime((lambda x=datetime.now(): x - timedelta(days=7))(), '/var/log/test_%Y-%m-%d.log')
        if os.path.exists(delfile): os.remove(delfile)
        # サイズローテーション
        ''' 
        handler = handlers.RotatingFileHandler(filename='/var/log/test.log',
                                               encoding='UTF-8',
                                               maxBytes=1048576,
                                               backupCount=3)
        '''
        # ログファイル設定
        handler.setLevel(INFO)
        handler.setFormatter(formatter)
        self.logger.addHandler(handler)
        # 標準出力用 設定: DEBUG レベルまで標準出力する
        sthandler = StreamHandler()
        sthandler.setLevel(DEBUG)
        sthandler.setFormatter(formatter)
        self.logger.addHandler(sthandler)

    def debug(self, msg):
        self.logger.debug(msg)
    def info(self, msg):
        self.logger.info(msg)
    def warn(self, msg):
        self.logger.warning(msg)
   def error(self, msg, exc_info=False):
        self.logger.error(msg, exc_info=exc_info)
    def critical(self, msg):
        self.logger.critical(msg)

この中の logger.error は、

    def error(self, msg, exc_info=False):
        self.logger.error(msg, exc_info=exc_info)

True 指定でスタックトレースも出るようにしている

print でスタックトレース標準エラー出力するなら、

import traceback
print(traceback.format_exc(), file=sys.stderr)