【PHP】ログローテート対応のログ出力関数を実装する

PHPではerror_logやsyslog等の汎用ログ出力関数が用意されており、
logrotate等と組み合わせることでログローテートを実現可能ですが、
ここでは自前でログローテート対応のログ出力関数を実装してみます。
 
処理の概要は下記のように非常にシンプルなもの。
・指定のログ出力先にログを出力
・ログが指定容量を超えたらローテートする(日付ではローテートしない)
・管理する世代数を超えたログは削除する
 
ソースはこのような感じ。

 

 
const LOG_DIRECTORY = '/var/log/logdir/';           // ログディレクトリ
const LOG_FILENAME  = 'logfname.log';               // ログファイル名
const LOG_FILEPATH  = LOG_DIRECTORY.LOG_FILENAME;   // ログのファイルパス
const MAX_LOTATES   = 3;                            // ログファイルを残す世代数
const MAX_LOGSIZE   = 1024*1024;                    // 1ファイルの最大ログサイズ(バイト)

function WriteLog($strlog){

    // 保存先ディレクトリを作成
    if(!file_exists(LOG_DIRECTORY)){
        mkdir(LOG_DIRECTORY);
    }

    // ログのローテート
    if(@filesize(LOG_FILEPATH) > MAX_LOGSIZE){

        // 最古のログを削除
        @unlink(LOG_FILEPATH.strval(MAX_LOTATES));

        // ログをリネーム .log → .log_01
        for ($i = MAX_LOTATES - 1; $i >= 0; $i--) {
            $bufilename = ($i == 0) ? LOG_FILEPATH : LOG_FILEPATH.strval($i);
            @rename($bufilename, LOG_FILEPATH.strval($i+1));
        }
    }

    // ログ出力 
    file_put_contents(LOG_FILEPATH, date('y-m/d-H:i:s ').$strlog."\n", FILE_APPEND | LOCK_EX);
}

 ※ローテート処理で関数名の頭に@が付いている箇所がありますが、

 ローテート対象ファイルがない場合に表示されるWarningを抑制するためです。

 詳しくは、PHPリファレンスのエラー制御演算子を参照 

 

この関数を呼び出すと、次のようにログ出力されます

 WriteLog("ログの出力てすと");
 $ cat login.log
 18-02/24-16:26:57 ログの出力てすと

 上記ソースでは各ファイルの最大サイズが1MiB、残すログは3世代分に設定されているため、logfname.logの容量が1MiBを越えるとログがローテートされます
logfname.log → logfname.log_1 → logfname.log_2 → logfname.log_3 → 削除

 

(拡張子に世代数を記載しない方が望ましいですが)