CodeIgniterは、ログ機能が貧弱ですが、Monologを使うことで解決ができます。
Monologを使えば、簡単に付加情報を出力したり、Syslogに出力したりできます。
概要
- アプリケーションログを、Monologで出力する
- CodeIgniter自身のログも、Monologで出力する
前提
- CodeIgniter 3.1.6
- Monolog 1.23.0
- PHP 7.2.1
composerでMonologをインストール
applicationディレクトリで、composerを実行します。
すると、application配下にvendorが作成され、vendor内にMonologとautoload.phpが作成されます。
$ cd application
$ composer require monolog/monolog
これは、CodeIgniterのcomposer_autoloadを有効にするだけで、自動的にロードさせるためです。
CodeIgniterのautoloadは、標準でapplication/vendor/autoload.phpをロードします。
CodeIgniterの設定
CodeIgniterのautoloadを有効にします。
$config['composer_autoload'] = TRUE;
ログ出力
アプリケーションログをMonologで出力させるだけであれば、必要な個所でLoggerを生成するだけです。
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
// Monologをuseします
// Processorsなど必要であれば、useを追加します
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
class Welcome extends CI_Controller {
public function index()
{
// Monologのオブジェクトを生成します
$log = new Logger('Sample');
// Syslogなどに出力する場合は、Handlerを変更することで可能です
$stream = new StreamHandler('./path/log.log');
$stream->setFormatter(new LineFormatter("%message%"));
$log->pushHandler($stream);
// ログを出力します
$log->info('test');
$this->load->view('welcome_message');
}
}
しかし、これだけではCodeIgniter自身で出力されるログが、Monologで出力されません。
CodeIgnierのログ出力
CodeIgniterでは、log_message()によってログが出力されます。
つまり、log_message()の処理を、Monologでの出力に変更する必要があります。
log_message()は、system/core/Common.phpでwrite_log()を呼び出していることがわかります。
そして、write_log()はsystem/core/Log.phpで定義されています。
$_log[0]->write_log($level, $message);
public function write_log($level, $msg)
Log.phpのwrite_log()をオーバーライドすれば、すべてのログ出力をMonologに変更できることがわかります。
CodeIgniterには、coreクラスを自作のcoreクラスに置き換えることが簡単にできる仕組みがあります。
Monolog出力用のログクラスを作成
coreのログクラス(CI_Log)を継承して、Monolog用のログクラス(MY_Log)を作成します。
write_log()をオーバーライドすることで、log_message()を変更します。
coreクラスを作成する際のプレフィックスは、configに設定されています。
$config['subclass_prefix'] = 'MY_';
自作のログクラスです。
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
// Monologをuseします
// Processorsなど必要であれば、useを追加します
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
class MY_Log extends CI_Log {
protected $log;
public function __construct()
{
// Monologのオブジェクトを生成します
$log = new Logger('Sample');
// Syslogなどに出力する場合は、Handlerを変更することで可能です
$stream = new StreamHandler('./path/log.log');
$stream->setFormatter(new LineFormatter("%message%"));
$log->pushHandler($stream);
}
public function write_log($level, $msg)
{
$log->{$level}($msg);
}
}
ログ出力は、通常と同じくlog_message()を呼び出すだけです。
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Welcome extends CI_Controller {
public function index()
{
// ログを出力します
log_message('info', 'test');
$this->load->view('welcome_message');
}
}
まとめ
- CodeIgniterのlog_message()は、CI_Logのwrite_log()である
- CI_Logを継承したログクラスで、write_log()をオーバーライドする