PythonをLinux環境で使用していて、ログをLinuxのシステムログに出力したいと思ったことがありました。
しかし、Linuxで使用できるNOTICEレベルのログを出力できない等、実環境で使うのに少し不便に思うことがあったので、使いやすいようカスタマイズすることにしました。
この記事では、loggingモジュールを使ってログをLinuxのシステムログに出力する方法と、ログレベルNOTICEを追加する方法を紹介します。
Python Logger Class
printでコンソールにメッセージを出力してもいいけれど、システムログに出力したい時や、レベルによって出力を絞りたい時等、色々便利です。
基本的な使い方はドキュメントにも書いてある通りになります。
import logging
logging.warning('出力したい文字列')
Linuxのシスログにログを出力する方法
handlersの設定を行い、出力先をLinuxのログデバイスに設定します。
サンプルコード:
import logging
from logging import handlers
LOG_DEVICE = "/dev/log" #LinuxOSのログデバイス
LOG_LEVEL = "debug" #実際に出力されるログはシスログプロセスが管理するので、debugにして全てのログを出力するようにします。
logger = logging.getLogger(name)
logger.setLevel(LOG_LEVEL)
logging.handlers.SysLogHandler(LOG_DEVICE) #出力先をLinuxのログデバイスに設定します。大体/dev/logになっています
ch.setLevel(LOG_LEVEL)
formatter = logging.Formatter('%(name)s [%(process)d]: %(message)s') #シスログの出力メッセージの形式に合わせて調整します
ch.setFormatter(formatter)
logger.addHandler(ch)
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
これでログがシステムログに出力されるようになりました。
システムログに出力されるログのレベルはシステムログ側の設定で絞ることができますので、Python側のレベル設定はdebugにしておきます。
Loggerのログレベルについて
現在loggingモジュールに用意されているログレベルは下記の5つだけ。
DEBUG
INFO
WARNING
ERROR
CRITICAL
Linuxのシステムログを使用するにあたって、もう少しログレベルを調整できるようにします。サンプルではNOTICEレベルを追加します。
ログレベルを追加するには、既存のloggerクラスを継承したクラスを作成してログレベルを追加していきます。
サンプルコード:
import logging
from logging import handlers
LOG_DEVICE = "/dev/log"
LOG_LEVEL = "debug"
NOTICE = 25 # ログレベルinfo(20), warning(30)の間の数にします
class UnixLogger(logging.Logger): # Loggerクラスを継承したクラスを作成
def __init__(self, name, level=logging.NOTSET):
super().__init__(name, level)
def notice(self, msg, *args, **kwargs): # noticeメソッドを定義
"""
Log 'msg % args' with severity 'NOTICE (25)'.
To pass exception information, use the keyword argument exc_info with
a true value, e.g.
logger.notice("Houston, we have a %s", "thorny problem", exc_info=1)
"""
if self.isEnabledFor(NOTICE):
self._log(NOTICE, msg, args, **kwargs)
# 追加部 ログレベルを追加してメソッドを追加したloggerクラスをセットする
logging.addLevelName(NOTICE, "NOTICE")
logging.handlers.SysLogHandler.priority_map.update({"NOTICE" : "notice"})
logging.setLoggerClass(UnixLogger)
logger = logging.getLogger(__name__)
logger.setLevel(LOG_LEVEL)
logging.handlers.SysLogHandler(LOG_DEVICE)
ch.setLevel(LOG_LEVEL)
formatter = logging.Formatter('%(name)s [%(process)d]: %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
logger.debug('debug message')
logger.info('info message')
logger.notice('notice message') # 追加したログレベルのメッセージを出力
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
これでnoticeレベルのログを簡単に出力できるようになりました。
他のレベルや、独自にログレベルをカスタマイズしたい場合でも同様に設定することができます。
サンプルコード公開
本記事のサンプルコードは、Github上に公開しています。