プログラムの保守や運用では不具合の発生条件の調査、改修結果の確認などのためにログ調査を行うことがよくあります。ログはシステムの動作を追跡し問題の診断やパフォーマンスの分析に不可欠な機能です。そのようなログですが様々な事情により複数の場所に分散して保存されることがしばしばあります(プログラム内の特定の機能のログだけ別に保存してる、サービス単位で保存場所が決まっているなど)。そういった時にログをそのまま保存すると追跡が手間になる時が多いです。追跡を楽にするためには各ログに追跡のための共通のIDを割り振るのが有効な手段です。PHPでこれを行う方法を紹介します。
サーバーでリクエストを受けて処理するPHPは1リクエストに対して1プロセスが立ち上がり、そのプロセスの中でリクエストを処理しきります。このためプロセス単位でIDを用意することによってリクエスト単位で共通なIDを扱えます。
実装方法は index.php などのリクエストを受けるエントリーポイントに次のようなIDを生成してグローバル変数に登録するコードを置き
global $_process_uid; $_process_uid = substr(base64_encode(random_bytes(24)), 0, 8);
このプロセスIDを各ログを保存するためのテンプレート内でを使えばそれでOKです。これは例えば次のように使えます。
/** PHP の error_log 関数と合わせて使う場合 */
function log_with_id($message) {
global $_process_uid;
$logMessage = "[{$_process_uid}] " . $message;
error_log($logMessage);
}
log_with_id('これはテストログです。');
/** LoggerInterface を使う場合*/
use Psr\Log\LoggerInterface;
class MyLogger implements LoggerInterface {
public function info($message, array $context = []) {
global $_process_uid;
$message = "[{$_process_uid}] " . $message;
//ファイルへの追記などの$messageをログに記録する処理をここに追加します
}
// LoggerInterfaceの他のメソッドも同様に実装します
}
/* MonoLog を使う場合 */
use Monolog\Logger;
use Monolog\Processor\ProcessorInterface;
// MonoLogにはログレコードに情報を追加するためのProcessorという仕組みがあり、これを使います
class UidProcessor implements ProcessorInterface {
public function __invoke(array $record) {
global $_process_uid;
// $_process_uidをログレコードの'extra'セクションに追加
$record['extra']['uid'] = $_process_uid;
return $record;
}
}
// ロガーインスタンスを作成
$logger = new Logger('log-with-uid-example');
// ログの出力先を設定。ここではファイルに出力
$logger->pushHandler(new \Monolog\Handler\RotatingFileHandler(__DIR__.'/tmp.log'));
// UidProcessorをロガーに追加して、すべてのログレコードに共通IDが含まれるようにする
$logger->pushProcessor(new UidProcessor());
// 使用例
$logger->info('これはテストログです。');
// 例えば tmp-2024-03-28.log に次のように出力されます
// [2024-03-28T08:52:10.931746+00:00] log-with-uid-example.INFO: これはテストログです。 [] {"uid":"NjEsAUwY"}
Laravelでこのようなログを作る場合、MonoLog形式のプロセッサを作り、次記事や「Laravel ログ Monolog 拡張」あたりの語で検索した時に出てくるページが参考になります。
【PHP】【Laravel】Monolog のログフォーマットを操作する│株式会社シーポイントラボ|浜松のシステム・RTK-GNSS開発
ログメッセージに一意のIDを割り振ることでログの追跡と分析が格段に楽になります。様々なライブラリやクラウドサービスにおいても似た機能があり、このあたりを使うことでより効率のよい作業ができます。