PHP アプリケーションのログ記録
最終更新日 2023年05月04日(木)
Heroku はログをストリームとして処理するため、stdout
または stderr
に送信されたアプリ、システム、API のすべてのログメッセージを自動的に集約して、アプリケーションのためのログ記録情報の単一のチャネルを提供します。
ほとんどの PHP フレームワークは適切なログ出力を書き込むように設定できるため、この記事では、いくつかの一般的なライブラリおよびフレームワークの例を示します。
PHP またはライブラリを使用したログ記録
プレーン PHP からのログ記録
通常の PHP エラーログは自動的に stderr
に送信されるため、error_log
関数を使用してログに記録されたすべてのメッセージを heroku logs
で入手できます。
error_log("hello, this is a test!");
代替アプローチとして、php://stderr
ストリームに直接書き込む方法があります。
file_put_contents("php://stderr", "hello, this is a test!\n");
stderr
に手動で書き込む場合は、上記の例のように、メッセージを常に末尾の改行文字で終了するようにしてください。
Monolog を使用したログ記録
PHP 用の優れた Monolog ライブラリを使用している場合は (これを推奨)、単純に StreamHandler
を使用して php://stderr
に書き込むことができます。
use Monolog\Level;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('name');
$log->pushHandler(new StreamHandler('php://stderr', Level::Warning));
$log->warning('Foo');
この例では、ロガーは “警告” 以上のレベルでメッセージをログに記録するのみです。その他の使用方法については、Monolog のドキュメントを参照してください。
Web フレームワークを使用している場合のログ記録
CodeIgniter 3.x
残念ながら、CodeIgniter ではそのログ記録機能の十分な設定が許可されておらず、カスタムコードを使用して機能を置き換えるためにコアクラスをクリーンに拡張する方法がありません。
回避方法として、“サブクラスプレフィックス” がデフォルトの “MY_” に設定されている場合は、次の内容を application/core/MY_Log.php
という名前のファイル (ファイル名は大文字と小文字が区別される) にドロップできます。
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
// this class is adapted from system/libraries/Log.php
/**
* CodeIgniter
*
* An open source application development framework for PHP 5.1.6 or newer
*
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
* @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://codeigniter.com/user_guide/license.html
* @link http://codeigniter.com
* @since Version 1.0
* @filesource
*/
// ------------------------------------------------------------------------
/**
* Logging Class
*
* @package CodeIgniter
* @subpackage Libraries
* @category Logging
* @author EllisLab Dev Team
* @link http://codeigniter.com/user_guide/general/errors.html
*/
class MY_Log {
protected $_threshold = 1;
protected $_date_fmt = 'Y-m-d H:i:s';
protected $_levels = array('ERROR' => '1', 'DEBUG' => '2', 'INFO' => '3', 'ALL' => '4');
/**
* Constructor
*/
public function __construct()
{
$config =& get_config();
if (is_numeric($config['log_threshold']))
{
$this->_threshold = $config['log_threshold'];
}
if ($config['log_date_format'] != '')
{
$this->_date_fmt = $config['log_date_format'];
}
}
// --------------------------------------------------------------------
/**
* Write Log to php://stderr
*
* Generally this function will be called using the global log_message() function
*
* @param string the error level
* @param string the error message
* @param bool whether the error is a native PHP error
* @return bool
*/
public function write_log($level = 'error', $msg, $php_error = FALSE)
{
$level = strtoupper($level);
if ( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
{
return FALSE;
}
file_put_contents('php://stderr', $level.' '.(($level == 'INFO') ? ' -' : '-').' '.date($this->_date_fmt). ' --> '.$msg."\n");
return TRUE;
}
}
// END Log Class
/* End of file MY_Log.php */
/* Location: ./application/core/MY_Log.php */
それにより、すべてのログ記録呼び出しが適切にログに記録されます。
CakePHP
アプリケーション設定で、ロガーの設定に ConsoleLog
エンジンを使用するよう CakePHP に指示します。
CakeLog::config('default', array(
'engine' => 'ConsoleLog',
));
その後、通常のログ記録方法を使用できます。
CakeLog::warning("Hello, this is a test message!");
詳細は、CakePHP のマニュアルの「Logging」(ログ記録) のセクションを参照してください。
Laravel
app/config/logging.php
で、さまざまなログ記録チャネルを設定できます。デフォルトでは、この設定ファイルには “errorlog
” チャネルの定義が含まれています。これにより、メッセージをログに記録するために PHP の独自のエラー処理が使用されるようになります。これらはその後、自動的に heroku logs
に送信されます。
このファイルの先頭では、デフォルトのチャネルが通常、LOG_CHANNEL
環境変数から読み取るように設定されています。
'default' => env('LOG_CHANNEL', 'stack'),
つまり、Heroku で適切にログ記録するには、LOG_CHANNEL
環境変数を “errorlog
” に設定するのみです。
$ heroku config:set LOG_CHANNEL=errorlog
Laravel 5.6 以降の新しいリリースでも、app/config/logging.php
に “stderr
” チャネルが定義されています。これは、まず PHP のエラーログメカニズムに進むのではなく heroku logs
に直接記録します。
$ heroku config:set LOG_CHANNEL=stderr
Lumen
Lumen フレームワークでは、前に説明した Laravel と同じメカニズムが使用されます。
推奨される設定として、次のように LOG_CHANNEL
を stderr
に設定します。
$ heroku config:set LOG_CHANNEL=stderr
Symfony
手順については、「Deploying Symfony Apps」(Symfony アプリのデプロイ) ガイドの「Logging」(ログ記録) のセクションを参照してください。
レガシーアプリケーションのためのログ記録の追加
一部のアプリケーションは、ログを stderr
または stdout
に書き込むように簡単に変更できません。これらの場合は、そのアプリケーションで静的なログファイル名の設定が許可されていれば、PHP アプリケーション用のブートスクリプトの -l
オプションを使用して、このようなログファイルを Logplex ストリームに tail
するよう Heroku の PHP サポートに指示することができます。
たとえば、レガシーアプリケーションが log/error.log
という名前のファイルに書き込むと、Procfile
エントリは次のようになります。
web: heroku-php-apache2 -l log/error.log
複数のファイルを末尾監視するために -l
オプションを複数回指定することも、それを他のオプションやドキュメントルート引数と組み合わせることもできます。
web: heroku-php-nginx -C rewrites.conf -l log/error.log -l log/slow.log wwwroot/
明らかな理由により、レガシーアプリケーションが動的な (たとえば、現在の日付を含む) ログファイル名を作成する場合、この機能を動作させるには、代わりに固定された静的なログファイル名を使用するようにパッチを適用するか、または設定する必要があります。