PHP 8.3.4 / Ubuntu 22.04 / nginx + PHP-FPM の構成で、社内の集計バッチを動かしていたときに気づいた話です。データ量は1日あたりの処理行数が数十万、1プロセスあたりのメモリ上限は128M。PHP 8.3 に上げた直後から、ログに Deprecated: ... が出ているのにアプリ側のエラーハンドラが拾わず、監視に何も上がらない状態が数日続きました。
原因は set_error_handler のコールバックで error_reporting() を評価していなかったことでした。8.3 では deprecation の種類が増えており、E_ALL を前提にしたつもりでも、実行時の error_reporting が E_ALL & ~E_DEPRECATED に落ちている箇所がありました。ハンドラは呼ばれるが自前で握りつぶしていた、というより、ハンドラ内で level を見て return false していたのが実際の挙動です。
set_error_handler(function (int $no, string $str, string $file, int $line): bool {
if (!(error_reporting() & $no)) {
return false; // ここで握ると監視に届かない
}
throw new ErrorException($str, 0, $no, $file, $line);
});
この形にしてから deprecation が ErrorException として上がるようになり、バッチ側で catch して集計できるようになりました。代償は明確で、サードパーティの古いコードが吐く deprecation まで例外化されるため、@ 演算子や error_reporting(0) に依存した処理が軒並み落ちます。うちではベンダーコードの呼び出し区間だけ一時的に error_reporting(E_ALL & ~E_DEPRECATED) に落とすラッパーを挟みました。
効かないのは、FPM の php.ini で display_errors=Off かつ log_errors=On のとき、ハンドラをすり抜けたエラーがファイルにだけ出るケースです。あと @ 付きの式は 8.0 以降でも error_reporting() が一時的に 0 になるので、上のコードだと握れません。ここは @ を外すのが本筋ですが、外部SDKだと難しいことがあります。
同じように 8.3 へ上げて deprecation が監視に乗らない現象、どの層(FPM設定・ハンドラ・フレームワーク)で止めていますか。


0 条评论
还没有评论,写下第一条。