pythonでLOGしたことなかったのでやってみた。
ログの設定内容はsettings/config.py
にまとめて、main.py(root)
からimport
して使うかたちを取ることにした。
info
は頻繁にログ出力することからログローテーションをつかう。これにより、ログサイズが指定サイズ(maxByte
)を超えたら自動的に新しいログファイルが作成されることになる。backupCount
回まで作成したら、後ろから上書き(厳密には違うが)されていくので1ファイルがデカくなりすぎることはない。
settings/config.py
import os
"""
参考にした書き方
https://stackoverflow.com/questions/7507825/where-is-a-complete-example-of-logging-config-dictconfig
"""
import os
"""
参考にした書き方
https://stackoverflow.com/questions/7507825/where-is-a-complete-example-of-logging-config-dictconfig
"""
"""
ログ設計指針
https://qiita.com/nanasess/items/350e59b29cceb2f122b3
◆バッチ処理の例◆
INFO 処理開始時
INFO 途中経過
INFO 処理終了時
WARN イベント発生時
ERROR 例外発生時
INFO その他、必要に応じて
◆WEBアプリケーションの例◆
INFO リクエスト開始時 - 処理概要、実行クラス名、メソッド名
INFO 途中経過 - 実行条件、処理対象オブジェクトのキーとなる値等(customer_id, order_id 等)
INFO 処理終了時 - 実行結果(OK/NG 等)、リダイレクト先
WARN イベント発生時 - 画面に表示したエラーメッセージ等
ERROR 例外発生時 - 例外クラス、例外メッセージ
INFO その他、必要に応じて
"""
""" ★ Python ログレベルについて ★
DEBUG 10 問題探求に必要な詳細な情報を出力したい場合
INFO 20 想定内の処理が行われた場合
WARNING 30 想定外の処理やそれが起こりそうな場合
ERROR 40 重大な問題により、機能を実行出来ない場合
CRITICAL 50 プログラムが実行不可となるような重大なエラーが発生した場合
"""
# PATH
SETTINGS_DIR = __file__ # ここのパス
ROOT_DIR = '/'.join(SETTINGS_DIR.split('/')[:-2]) # rootは1つ上の階層
LOG_DIR = os.path.join(ROOT_DIR, 'logs')
MAIN_LOG_DIR = os.path.join(LOG_DIR, 'main') # main.py用
NB_LOG_DIR = os.path.join(LOG_DIR, 'notebook') # jupytenotebook用
# ディレクトリ作成
if not os.path.exists(LOG_DIR):
os.mkdir(LOG_DIR)
if not os.path.exists(MAIN_LOG_DIR):
os.mkdir(MAIN_LOG_DIR)
if not os.path.exists(NB_LOG_DIR):
os.mkdir(NB_LOG_DIR)
LOGGING_CONFIG = {
'version': 1,
# loggersで''として指定してもOK
# 'root': {
# 'level': 'NOTSET',
# 'handlers': ['debug_console_handler', 'info_rotating_file_handler', 'error_file_handler'],
# },
'loggers': {
'': { # root
'level': 'NOTSET',
'handlers': ['debug_console_handler', 'info_rotating_file_handler', 'error_file_handler'],
},
'notebook': {
'level': 'NOTSET',
'handlers': ['info_notebook', 'error_notebook'],
},
},
'handlers': {
'debug_console_handler': {
'level': 'DEBUG',
'formatter': 'info',
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
},
# ログ・ファイルのサイズがmaxBytes以上になったらinfo1.2.3..nと
# 新しいログファイルを作成(rotating)する
# backupCount回まで作成したら、後ろから上書きされていく(厳密には違うが)
'info_rotating_file_handler': {
'level': 'INFO',
'formatter': 'info',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(MAIN_LOG_DIR, 'info.log'),
'mode': 'a',
'maxBytes': 1048576, # 1MBまで
'backupCount': 10 # 10ローテ
},
'error_file_handler': {
'level': 'ERROR',
'formatter': 'error',
'class': 'logging.FileHandler',
'filename': os.path.join(MAIN_LOG_DIR, 'error.log'),
'mode': 'a',
},
'info_notebook': {
'level': 'INFO',
'formatter': 'info',
'class': 'logging.handlers.RotatingFileHandler',
'filename': os.path.join(NB_LOG_DIR, 'info.log'),
'mode': 'a',
'maxBytes': 1048576, # 1MBまで
'backupCount': 10 # 10ローテ
},
'error_notebook': {
'level': 'ERROR',
'formatter': 'error',
'class': 'logging.FileHandler',
'filename': os.path.join(NB_LOG_DIR, 'error.log'),
'mode': 'a',
},
},
'formatters': {
'info': {
'format': '%(asctime)s-%(levelname)s-%(name)s::%(module)s|%(lineno)s:: %(message)s'
},
'error': {
'format': '%(asctime)s-%(levelname)s-%(name)s-%(process)d::%(module)s|%(lineno)s:: %(message)s'
},
},
}
https://blog.hiros-dot.net/wp-content/uploads/2021/01/ScreenShot_55.jpg
main.py
from logging import getLogger,config
from settings.config import LOGGING_CONFIG
config.dictConfig(LOGGING_CONFIG)
logger = getLogger()
for i in range(1000):
if i % 2 ==0:
logger.info(i)
if i % 3 == 0:
logger.error(i)
出力
2022-01-10 12:09:55,249-INFO-root::899213607|14:: 0
2022-01-10 12:09:55,250-ERROR-root::899213607|16:: 0
2022-01-10 12:09:55,251-INFO-root::899213607|14:: 2
2022-01-10 12:09:55,252-ERROR-root::899213607|16:: 3
2022-01-10 12:09:55,253-INFO-root::899213607|14:: 4
2022-01-10 12:09:55,253-INFO-root::899213607|14:: 6
2022-01-10 12:09:55,254-ERROR-root::899213607|16:: 6
2022-01-10 12:09:55,256-INFO-root::899213607|14:: 8
2022-01-10 12:09:55,256-ERROR-root::899213607|16:: 9
2022-01-10 12:09:55,257-INFO-root::899213607|14:: 10
2022-01-10 12:09:55,258-INFO-root::899213607|14:: 12
2022-01-10 12:09:55,258-ERROR-root::899213607|16:: 12
2022-01-10 12:09:55,260-INFO-root::899213607|14:: 14
2022-01-10 12:09:55,260-ERROR-root::899213607|16:: 15
2022-01-10 12:09:55,262-INFO-root::899213607|14:: 16
2022-01-10 12:09:55,262-INFO-root::899213607|14:: 18
2022-01-10 12:09:55,263-ERROR-root::899213607|16:: 18
2022-01-10 12:09:55,264-INFO-root::899213607|14:: 20
2022-01-10 12:09:55,265-ERROR-root::899213607|16:: 21
2022-01-10 12:09:55,266-INFO-root::899213607|14:: 22
2022-01-10 12:09:55,267-INFO-root::899213607|14:: 24
2022-01-10 12:09:55,268-ERROR-root::899213607|16:: 24
2022-01-10 12:09:55,269-INFO-root::899213607|14:: 26
2022-01-10 12:09:55,270-ERROR-root::899213607|16:: 27
2022-01-10 12:09:55,271-INFO-root::899213607|14:: 28
2022-01-10 12:09:55,272-INFO-root::899213607|14:: 30
2022-01-10 12:09:55,272-ERROR-root::899213607|16:: 30
2022-01-10 12:09:55,274-INFO-root::899213607|14:: 32
2022-01-10 12:09:55,275-ERROR-root::899213607|16:: 33
2022-01-10 12:09:55,275-INFO-root::899213607|14:: 34
2022-01-10 12:09:55,277-INFO-root::899213607|14:: 36
2022-01-10 12:09:55,278-ERROR-root::899213607|16:: 36
2022-01-10 12:09:55,279-INFO-root::899213607|14:: 38
2022-01-10 12:09:55,280-ERROR-root::899213607|16:: 39
2022-01-10 12:09:55,281-INFO-root::899213607|14:: 40
2022-01-10 12:09:55,281-INFO-root::899213607|14:: 42
2022-01-10 12:09:55,282-ERROR-root::899213607|16:: 42
2022-01-10 12:09:55,284-INFO-root::899213607|14:: 44
2022-01-10 12:09:55,285-ERROR-root::899213607|16:: 45
2022-01-10 12:09:55,286-INFO-root::899213607|14:: 46
2022-01-10 12:09:55,287-INFO-root::899213607|14:: 48
2022-01-10 12:09:55,288-ERROR-root::899213607|16:: 48
2022-01-10 12:09:55,288-INFO-root::899213607|14:: 50
2022-01-10 12:09:56,121-INFO-root::899213607|14:: 994
2022-01-10 12:09:56,122-INFO-root::899213607|14:: 996
2022-01-10 12:09:56,124-ERROR-root::899213607|16:: 996
2022-01-10 12:09:56,125-INFO-root::899213607|14:: 998
2022-01-10 12:09:56,126-ERROR-root::899213607|16:: 999