Curry
PHP Framework

ログ出力

ログ出力の準備

CurryではLoggerクラスを利用することでログの出力が容易に行えます。
Loggerクラスのメソッドは全て静的メソッドであるため、出力ロジックの記述位置を選ばず、手軽にログ出力が可能です。

デフォルトでログ出力されるようになっています。
出力先のディレクトリは標準ではシステムのルートディレクトリ直下のlogsディレクトリで、出力ファイルはsystem.logです。

ファイル名を変更したい場合はcurry.iniまたはInitializerで設定します。

curry.ini
[logger]
;--If you want to output log, set log file name.
system_log = "custom.log"

;--If you want to output query log, set log file name.
query_log = "query.log"
index.php
class Initializer extends InitializerStandard
{
    public function initialize()
    {
        Logger::setLogName('custom.log')
    }
}

curry.iniでは、システムログとクエリログのファイル名指定が可能です。
システムログは、Logger::info等のログ出力メソッドにより出力されるログファイルです。
クエリログは、ModelやSqlAbstractを継承したクラスを使用して実行されたSQLが全て出力されるログファイルです。

setLogNameメソッドで設定する場合は実行する場所はどこでもかまいません。
システム全体で一つのログファイルに出力するならばInitializerで設定してしまうのが良いでしょう。例えばコントローラーごとに出力するファイルを別にする場合は、それぞれのコントローラークラスのpreProcessメソッドなどで定義すればよいし、コントローラーのサブディレクトリ単位にファイルを別にする場合はPluginのpreProcessに記述すればよいでしょう。

ログの出力

setLogNameメソッドさえ通せば、後は好きな場所でログ出力メソッドを呼び出すだけです。
ログにはログレベルという概念が存在し、出力するログの種類により、使い分けることで、ログファイルを読み取りやすくすることが出来ます。

ログレベルには以下の5つが存在します。

ログレベルメソッド意味
デバッグ debug 開発時のデバッグ目的や運用時の検証などに利用する。特定のポイントの変数の内容を知りたいなど、一時的に意図的に埋め込む。
情報 info 通常の通知レベルのログ。処理の経過などの意味合い。
警告 warn 致命的ではないが、注意が必要な処理が行われた場合などのログに利用。
エラー error 想定される不正処理やcatchブロック内で利用。
例外 except catchブロックでの利用を想定。引数に例外のインスタンスを渡すことで例外の内容を出力してくれる。

実際のところ、exceptメソッドを除いて、ログの中に[INFO]や[ERROR]などの文字列が含まれるだけで、それ以外の違いは在りません。ログファイルを参照した時に、例えばエラーのログだけを探したい場合のインデックス的な役割をするだけのものです。
except以外のメソッドは引数には出力したいメッセージを指定するだけです。exceptは例外のインスタンスを指定します。exceptは出力されるログレベルの表示はerrorメソッドと同じ、[ERROR]になります。

利用頻度が高いのはinfoやerrorでしょう。infoは処理経過をロギング、想定されたエラー処理時にerrorで記録を残す、というところです。

Logger::info('処理を開始しました。');
Logger::warn('存在しないアクションへアクセスがありました。');
Logger::error('処理が異常終了しました。');
Logger::debug($var);
try {
    throw new Exception('例外です');
} catch (Exception $e)
    Logger::except($e);
}
[2011-01-01 00:00:00] [INFO ] 処理を開始しました。
[2011-01-01 00:00:00] [WARN ] 存在しないアクションへアクセスがありました。
[2011-01-01 00:00:00] [ERROR] 処理が異常終了しました。
[2011-01-01 00:00:00] [DEBUG] hogehoge。
[2011-01-01 00:00:00] [ERROR] FILE:/home/・・・/controllers/index_controller.php LINE:18 例外です。
#0 D:\public_html\curry\dispatcher.php(188): IndexController->index()
#1 D:\public_html\curryfw\htdocs\index.php(41): Dispatcher->dispatch()
#2 {main}

出力レベルの制限

例えば開発環境では全てのログを出力し、
公開環境ではdebugレベルのログ出力は行わないといったような指定をしたい場合があります。

Loggerは実際にログファイルに出力するログのレベルの下限を設定することが出来ます。

Logger::setOutputLevel(LogLevel::INFO);

setOutputLevelメソッドで出力するログレベルの下限を設定しますが、レベルはLogLevelクラスのクラス定数で指定します。

ログレベルLogLevelクラスの定数
デバッグ LogLevel::DEBUG
情報 LogLevel::INFO
警告 LogLevel::WARN
エラー LogLevel::ERROR
例外 LogLevel::EXCEPT
一切出力なし LogLevel::NO_OUTPUT

例えばLogLevel::INFOを設定した場合、INFOレベル以上のログ出力しか行いません。
つまり、Logger::debugメソッドによるログ出力は無視されます。

ちなみにこの設定はcurry.iniでの初期設定でも可能です。

curry.ini
[logger]
;--if you want to set numeric min level of log output.
;--set value as string "debug" or "info" or "warn" or "error" or "except" or "no_output"
output_level = "info"

出力レベルの初期値はDEBUGで、すべてのレベルのログが出力されます。

出力フォーマットの指定

ログのフォーマット

デフォルトではログの出力フォーマットは以下のようになっています。

[時間] [ログレベル] メッセージ

これは任意に指定することが出来ます。指定にはsetLogFormatメソッドを利用します。
デフォルトのフォーマット指定は以下のような感じです。

[%time%] [%level%] %message%

%time%の位置に、出力される瞬間の時刻、
%level%の位置にログレベルの表示、
%message%の位置にログメッセージが出力されます。

例えば、

Logger::setLogFormat('%time% %message%(%level%)');

とした場合、

2011-01-01 00:00:00 処理を開始しました。(INFO)

のように出力されます。

時間のフォーマット

%time%の位置に自動的に時間が出力されますが、デフォルトのフォーマットは、yyyy-MM-dd HH:mm:ssという感じになっており、PHPの時間指定フォーマットで表現すると"Y-m-d H:i:s"です。setLogFormatメソッドでは時間の出力位置は指定できますが、時間自体のフォーマットが指定できません。これは、setTimeFormatメソッドにより指定が可能です。

Logger::setTimeFormat('Y/n/j H:i:s');
Logger::info('処理を開始しました。');

とした場合、

[2011/1/1 00:00:00] [INFO ] 処理を開始しました。

のように出力されます。
指定するフォーマットはdate関数に指定するのと同じ、PHPの時刻指定フォーマットです。

ログのローテート

Loggerはローテートの仕組みを持っています。
ローテートとはログファイルの世代保存の仕組みで、1ファイルの行数が規定に達したら旧世代のファイルとしてリネームして退避します。
Loggerでは、この保存世代数の最大値と、1ファイルの最大行数の設定が行えます。

// 1ファイルの最大出力行数を設定
Logger::setMaxLine(1000);
// ログファイルの保存世代最大数を設定
Logger::setGeneration(5);

この設定はInitializerなどで行うとよいでしょう。
またはcurry.iniでの設定も可能です。

[logger]
;--if you want to set max output lines.
max_line = "1000"

;--if you want to set max output lines.
max_generation = "5"

この例では1ファイルが1000行に達したらそのファイルはファイル名の末尾に世代番号を付加して退避します。
そして世代番号なしの最新ログを含めたファイル数が5ということになります。
最大世代数まで退避されている状態で新たな世代に入る場合は、最古の物が削除されます。

∟site/
    ∟logs/
        ∟system.log
        ∟system.log.1
        ∟system.log.2
        ∟system.log.3
        ∟system.log.4

最大世代数に達している状態時はこのような感じになり、
世代数5の場合は".4"のログファイルが最古になります。
この状態で世代交代が発生すると".4"が削除され、各世代の世代番号が1つずつ加算され、新たに世代番号なしのファイルが作成されます。

最大行数の初期値は100000行、最大世代数の初期値は3です。