2020年9月20日日曜日

Pythonでログローテーションする

 Pythonには標準でloggingというロギング機能があって、ファイルへのログ出力もできる。ただ、24時間動作し続けるプログラムだとログがたまってログファイルが巨大になることもあれば、日ごとのログファイルを作成したいこともある。今回はPythonでログローテーションをしてみる。


環境


WSL(Ubuntu18.04)。


loggingを使ってみる

とりあえず、loggingを使ってみる。

from logging import getLogger, basicConfig

#ロガーの名前を指定
logger = getLogger(__name__)

# ロギングのレベルをDEBUGにしてログフォーマットを変更
FORMAT = '%(asctime)s %(name)s %(levelname)s %(funcName)s %(message)s'
basicConfig(level='DEBUG', format=FORMAT, datefmt='%Y/%m/%d %H:%M:%S')
logger.debug('隣の芝生は青い')
以下のようなログが出力される。


ファイルへのログ出力

loggingにはログ出力方法が違うハンドラーがいくつかある。ファイルへログを出力するにはbasicConfigのhandlersにログをファイルへ出力するハンドラー(FileHandler)を指定する。

from logging import getLogger, basicConfig, FileHandler

#ロガーの名前を指定
logger = getLogger(__name__)

# ロギングのレベルをDEBUGにしてログフォーマットを変更
# handlersを指定してログファイルへ出力
FORMAT = '%(asctime)s %(name)s %(levelname)s %(funcName)s %(message)s'
handler = FileHandler(filename='test.log')
basicConfig(handlers=[handler], level='DEBUG', format=FORMAT, datefmt='%Y/%m/%d %H:%M:%S')
logger.debug('隣の芝生は青い')

test.logに以下のようなログが出力される。


dict形式の設定を使う

loggingではdict形式で指定した設定を使える。複数のハンドラーを使ったり細かく設定したりしたい場合は設定をまとめられるので扱いやすい。

from logging import getLogger, config

# loggingの設定
logging_config = { 
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': { 
        'logfile': { 
            'format': '%(asctime)s %(name)s %(levelname)s %(funcName)s %(message)s',
            'datefmt': '%Y/%m/%d %H:%M:%S'
        },
    },
    'handlers': { 
        'logfile': { 
            'formatter': 'logfile',
            'class': 'logging.FileHandler',
            'filename': 'test.log',
            'mode': 'a',
        },
    },
    'loggers': { 
        '__main__': { 
            'handlers': ['logfile'],
            'level': 'DEBUG',
            'propagate': False
        },
    } 
}
config.dictConfig(logging_config)

#ロガーの名前を指定
logger = getLogger(__name__)

logger.debug('隣の芝生は青い')

先のtest.logと同様の出力結果が得られる。


ログローテーションをする

いよいよログローテーションをしてみる。loggingにはRotatingFileHandlerとTimedRotatingFileHandlerというハンドラーがあって、それぞれファイルサイズ、指定した時間などでファイルがローテンションする。RotatingFileHandlerは指定したファイル名の末尾に連番がふられていき、TimedRotatingFileHandlerの場合はファイル名の末尾に日付がふられていく。ともにbackupCountで保存するファイル数を指定できる。

from logging import getLogger, config

# loggingの設定
logging_config = { 
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': { 
        'logfile': { 
            'format': '%(asctime)s %(name)s %(levelname)s %(funcName)s %(message)s',
            'datefmt': '%Y/%m/%d %H:%M:%S'
        },
    },
    'handlers': { 
        'rorating': { 
            'formatter': 'logfile',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'rotating.log',
            'mode': 'a',
            'maxBytes': 5000,
            'backupCount': 10
        },
        'timerotating': { 
            'formatter': 'logfile',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': 'timerotating.log',
            'when': 'midnight',
            'backupCount': 30,
        },
    },
    'loggers': { 
        '__main__': { 
            'handlers': ['rotating', 'timerotating'],
            'level': 'DEBUG',
            'propagate': False
        },
    } 
}
config.dictConfig(logging_config)

#ロガーの名前を指定
logger = getLogger(__name__)

logger.debug('隣の芝生は青い')

2つのそれぞれのハンドラーで指定したrotating.logとtimerotating.logにログが出力され、ローテーションした際にはファイル末尾に連番や日付がつく。


0 件のコメント:

コメントを投稿