Perlからログを出力方法
ここからは、実際にPerlでログを出力する方法をコードを交えながら説明します。
Perlのスクリプトから最も簡単にログを吐くには、組込み関数のwarnを使います。
これを実行すると、標準出力に対して、
のようにwarnを記したファイル名と行があわせて出力されます。
しかしこれだけでは前節で説明したログに必要な項目を満たしていないので、情報を追加していきます。
(1)で日付時刻を追加し、(2)でログのレベルを指定しています。実際に実行すると、
となり、時間とログレベルを追加できました。
ただしログを出力するたびにこのコードを書くのは冗長ですので、再利用できるようにします。リスト3が完成した関数になります。
実行方法と出力は次のようになります。
そのままlogf関数内でwarnを実行すると、logfを呼んだファイル名・行ではなく、warnを呼んだlogf内のファイル名・行が出力されてしまうので、リスト3(1)でcaller関数を使い呼び出し元の情報を得ています。そしてリスト3(2)でwarnにてログを書き出すのですが、その際は改行を最後に付け、warnが必要のないファイル名・行を追加しないようにします。
これで、シンプルで再利用可能なログ関数を作ることができました。
CPANに登録されているログモジュール
前節ではログを出力するための簡単な関数を作成してみましたが、ログを出すためのモジュールはすでにCPANに多く登録されています。本節ではCPANに登録されている代表的なログモジュールをいくつか紹介します。
Log::Log4perl
Log::Log4perlは、その名のとおりJavaでよく使われるログツールLog4JのPerl版となります。Log::Log4perlはcpanmコマンドにて簡単に導入できます。
基本的な使い方はリスト4のようになります。まず(1)でログの出力方法を定義した設定ファイルを読み込みます。次に(2)で使用するloggerオブジェクトを作成し、(2)以降でログを出力します。ログを出力するメソッドはレベルごとにtrace、debug、info、warn、error、fatalの6つが用意されています。
リスト5はリスト4(1)で読み込む設定ファイルです。1行目でloggerを定義します。ここではdevelopというloggerを作成し、出力するレベルをDEBUG以上、ログ出力方法としてScreenという設定を使うと宣言しています。2行目以降は出力方法の定義です。2行目ではログを出力するモジュールとしてLog::Log4perl::Appender::Screen(標準エラーにログを出力)を指定し、3行目、4行目でログの形式を設定しています。各設定の詳しい内容はモジュールのドキュメントを確認してください。
log4perl.plを実行すると、リスト6のような結果が得られます。ログのレベルやログの呼び出し元も出力されています。Log4perlでは標準エラーにログを吐き出すモジュールのほかに、ファイルやデータベースに書き込むモジュールも用意されており柔軟なカスタマイズができます。
Log::Dispatch
Log::DispatchはDateTimeやMooseの開発者として知られているDave Rolsky氏によるログモジュールで、拡張性が高いのが特徴であり、CPANにも多くの拡張モジュールやフレームワークのプラグインが登録されています。
リスト7がLog::Dispatchの基本的な使い方です。(1)でLog::Dispatchのインスタンスを作成します。サンプルでは出力方法として、(2)で標準出力あるいは標準エラーに書き出すScreenモジュールを採用しています。Log::Dispatchはインスタンス作成時に複数の出力モジュールを指定することで、同時にさまざまなログ出力方法が利用できます。(2)以降でログを吐き出しています。Log4perlと同様にログレベルごとのメソッドが用意されています。サポートされているのはdebug、info、notice、warning、error、critical、alert、emergencyの8個です。
しかしLog4perlと異なり、Log::Dispatchではログレベルや時刻、ログ呼び出し元の情報がログに一切含まれません。リスト7を実行しても、
というメッセージだけが表示され、ログとしての必要項目が満たせていません。そこでインスタンス作成時にリスト8のようにコールバックを追加します。これでLog4perlと同じ結果が得られます。
Log::Minimal
Log::Minimalは拙作のログモジュールで、極力シンプルに利用できるよう設計されています。
リスト9はLog::Minimalの利用例です。Log::Minimalをuseするといくつかの関数がエクスポートされるので、それを使いログを出力します。インスタンスの作成などが必要なく、少ない手数でログを書けます。サポートしているログレベルはcritical、warn、info、debugの4つで、それぞれcritf、warnf、infof、debugfという関数が用意されています。さらに、warnffのように「f」が2つ付く関数もあり、こちらはスタックトレースが付加されます。
Log::Minimalはシンプルながらもいくつかカスタマイズできるようになっているので、以降で紹介します。
デバッグメッセージの表示
Log::Minimalでdebugfもしくはdebugffを使っても、標準ではそのログは出力されません。LM_DEBUGという環境変数を有効にすることで初めて、デバッグメッセージが出力されるようになります。
アプリケーション開発中はLM_DEBUGを有効にし、本番環境では無効にすることで、本番環境で必要のないログを残さないようにできます。
ログのカラーリング
ターミナル上でログを表示した際に、ログメッセージに色を付けることができます。$Log::Minimal::COLOR変数に1を入れると色付け機能が有効になります。ログに色を付けることで開発時にログが見やすくなるでしょう。
次のコードを実行すると、図1のようにメッセージ部分がカラーリングされターミナルに表示されます。
なお、Log::Log4perlではLog::Log4perl::Appender::ScreenColoredLevels(ディストリビューション同梱)、Log::DispatchではCPANに登録されているLog::Dispatch::Screen::Colorモジュールを利用することで、同じようにログに色を付けることができます。
メッセージのフォーマットと自動シリアライズ
Log::Minimalのログ出力関数に2つ以上の引数を渡すと、1つ目をprintfのフォーマット文字列として利用します。
上記は、次のようにフォーマットされて表示されます。
また、$Log::Minimal::AUTODUMP変数に1を代入しておくと、ハッシュや配列のリファレンスやオブジェクトをログ関数に渡した場合、自動的にシリアライズして出力します。
上記のコードを実行すると、リスト10のように展開されてログ出力されます。環境変数や追加情報・デバッグ情報の表示に便利です。
ログ出力方法の変更
デフォルトのLog::Minimalは、warn関数を通して標準エラーにログを出力しています。もし出力方法をカスタマイズをしたい場合は、$Log::Minimal::PRINTという変数を上書きします。リスト11ではファイルにログを記録するよう変更しています。
$Log::Minimal::PRINTに渡したサブルーチンリファレンスには、フォーマットされた時刻、ログレベル、メッセージ、呼び出し元の情報が渡されるので、自由に情報の追加/削除を行って、ログの書き出しができます。
ログモジュールの比較
ここまで紹介したLog::Log4perl、Log::Dispatch、Log::Minimalの機能比較を表2にまとめました。CPANにはこれ以外にも数多くのログモジュールが登録されていますが、それらを選択する際の参考していただければと思います。個人的には時間や書き出し元の情報がデフォルトで追加され、ログを書き出すという目的まで最も手間が少ない拙作のLog::Minimalをお勧めします。
表2 ログモジュールの比較
モジュール名 | 時間・ログ書き出し元の表示 | ログレベル数 | ログ出力方法のカスタマイズ | ログのカラーリング | フォーマットシリアライズ機能 | 速度 |
Log::Log4perl | ○ | 6 | 拡張モジュールあり | ○ | × | △ |
Log::Dispatch | callbackで実装 | 8 | 拡張モジュールあり | 別途CPANモジュール | × | × |
Log::Minimal | ○ | 4 | 自前で用意する必要あり | ○ | ○ | ○ |
※ 速度についてはhttp://d.hatena.ne.jp/tori243/20110704/1309779334を参考にした