logging ログ出力 その4

これまでログ出力の設定を直接コードに記述したサンプルを見てきましたが、実運用上はログの設定は設定ファイルを使用することが多いですね。このページではログの設定ファイルについて学習しましょう。

ini形式による設定

ログの設定使用できる設定ファイルにはyaml形式(というか辞書形式)とini形式があります。まずはini形式について説明します。

設定ファイルには、フォーマッタ、ハンドラ、ロガーの設定を記述しますが、考え方としてはコードに直接記述した時と同様、ロガーに対し、複数のハンドラーを設定し、それぞれのハンドラーには1つのフォーマッタを設定するだけです。rootロガーを設定するサンプルを見てみましょう。

;logconf.ini


[loggers]
keys=root

[handlers]
keys=h1

[formatters]
keys=fmt1

; 以下、フォーマッター、ハンドラー、ロガーの個別設定

; フォーマッター
[formatter_fmt1]
format=%(asctime)s %(name)s %(levelname)s %(message)s
class=logging.Formatter

; ハンドラー
[handler_h1]
class=StreamHandler
level=DEBUG
formatter=fmt1
args=(sys.stdout,)

;ロガー
[logger_root]
level=NOTSET
handlers=h1

使用する側のpythonファイルは以下のようになります。

import logging.config

logging.config.fileConfig('logconf.ini')
logger = logging.getLogger(__name__)
logger.error('エラーが発生しました')

h1というハンドラーをrootロガーに設定しています。また、fmt1というフォーマッターをh1に設定しています。なお、上のサンプルはあくまでも説明用なので、実運用では働きがわかるような名前を設定したほうが良いでしょう。iniファイルのセクションは以下から構成されます。

セクション名 内容
loggers 使用するロガーの名前をカンマ区切りで列挙
handlers 使用するハンドラーの名前をカンマ区切りで列挙
formatters 使用するフォーマッターの名前をカンマ区切りで列挙
logger_ロガー名 ロガーの個別設定。rootロガー以外はqualnameにてロガー名を設定。
handler_ハンドラー名 ハンドラーの個別設定。
classで使用するハンドラーのクラスを指定。
argsでハンドラー生成時の引数を指定。
formatter_フォーマッター名 フォーマッターの個別設定

複数のロガーを設定

では、もうひとつサンプルです。今度は複数のロガーを設定して、標準出力とファイルの両方にログを出力してみます。対象とするロガーの名前はsampleとしましょう。

;logconf.ini
                                                                                                          

[loggers]                                                                                                 
keys=root, sample

[handlers]                                                                                                
keys=h1, h2                                                                                               
                                                                                                          
[formatters]                                                                                              
keys=fmt1, fmt2

; 以下、フォーマッター、ハンドラー、ロガーの個別設定

; フォーマッター
[formatter_fmt1]
format=%(asctime)s %(name)s %(levelname)s %(message)s [fmt1]
class=logging.Formatter

[formatter_fmt2]
format=%(asctime)s %(name)s %(levelname)s %(message)s [fmt2]
class=logging.Formatter


; ハンドラー
[handler_h1]
; 標準出力
class=StreamHandler
level=DEBUG
formatter=fmt1
args=(sys.stdout,)

[handler_h2]
; ファイル出力
class=FileHandler
level=DEBUG
formatter=fmt2
args=('sample.log',)

;ロガー
[logger_root]
level=NOTSET
handlers=h1

[logger_sample]
level=NOTSET
handlers=h2
qualname=sample

import logging.config
                                                                                                          
logging.config.fileConfig('logconf.ini')

logger = logging.getLogger('sample')
logger.error('エラーが発生しました')

上のコードを実行してみると、sampleロガーにはrootロガーで設定したログが標準出力に、sampleロガーで設定したログがファイルに、と2種類のログが出力されることが確認できます。