錯誤追蹤、回報非常重要,看到的錯誤才知道怎麼修。
現今 PHP 流行的 Laravel 有很好的 Error Tracking, Error Handling。但 plain PHP 怎麼辦呢?
在 production 為了安全考量會設定 error_reporting(0); 🙈 隱藏錯誤訊息,但…眼不見為淨了嗎?
“silent error” 是非常可怕的!! 能正確的記錄錯誤訊息才能有效 debug。
使用 PHP 原生方式將 PHP 錯誤訊息傳送至 Slack 進行通知與記錄。
線上服務常常因為快速開發、快速上線或安全考量,進而關閉錯誤訊息。
但是… 壞掉的時候怎麼辦? 怎麼修? 是誰壞了?
然而~
只要做好錯誤處理(Error Tracking、Error Handling) 就算把錯誤訊息關閉
也不要緊~
error_reporting(0);
透過下面兩個的方式,依然可以截取 PHP 錯誤訊息。
PHP 原生函式
https://www.php.net/manual/en/function.set-error-handler.php
設定一個 function 負責接收處理錯誤內容(error_handler)
透過這個 function 分別可以取得相關訊息為…
example code: set_error_handler()
為 PHP 原生函式
https://www.php.net/manual/en/function.register-shutdown-function.php
同上,設定一個 function 負責處理
這個 function 會在以下幾種情況被呼叫:
再配合 error_get_last(),就能取得當下的錯誤、異常訊息~
example code: register_shutdown_function()
說那麼多,直接上 code!!!
開始前~ 先申請 slack webhook API,取得 api url(token)
先準備好,一個 slack workspace,然後透過 incoming webhook 處理訊息
https://api.slack.com/incoming-webhooks
https://slack.com/apps/A0F7XDUAZ-incoming-webhooks
進行一些簡單設定後
.
.
.
可以選擇將訊息傳送至個人或 channel
準備一支 php file
(詳細內容,再依自己需求做調整,當然比較建議封裝成 class~)
<?php
// 全開或全關 php error
// error_reporting(E_ALL);
error_reporting(0);
// 取代為你自己的 slack webhook url
define('SLACK_WEBHOOK', 'https://hooks.slack.com/services/Txxxx5/B0xxxxxxxxxxxxxxxxx87s');
set_error_handler('common_error_handler');
register_shutdown_function("shutdown_error_handler");
function FriendlyErrorType($type)
{
switch ($type) {
case E_ERROR: // 1 //
return 'E_ERROR';
case E_WARNING: // 2 //
return 'E_WARNING';
case E_PARSE: // 4 //
return 'E_PARSE';
case E_NOTICE: // 8 //
return 'E_NOTICE';
case E_CORE_ERROR: // 16 //
return 'E_CORE_ERROR';
case E_CORE_WARNING: // 32 //
return 'E_CORE_WARNING';
case E_COMPILE_ERROR: // 64 //
return 'E_COMPILE_ERROR';
case E_COMPILE_WARNING: // 128 //
return 'E_COMPILE_WARNING';
case E_USER_ERROR: // 256 //
return 'E_USER_ERROR';
case E_USER_WARNING: // 512 //
return 'E_USER_WARNING';
case E_USER_NOTICE: // 1024 //
return 'E_USER_NOTICE';
case E_STRICT: // 2048 //
return 'E_STRICT';
case E_RECOVERABLE_ERROR: // 4096 //
return 'E_RECOVERABLE_ERROR';
case E_DEPRECATED: // 8192 //
return 'E_DEPRECATED';
case E_USER_DEPRECATED: // 16384 //
return 'E_USER_DEPRECATED';
}
return "";
}
function shutdown_error_handler()
{
$lasterror = error_get_last();
$type = $lasterror['type'];
$typeName = FriendlyErrorType($type);
$message = $lasterror['message'];
$file = $lasterror['file'];
$line = $lasterror['line'];
if (isset($lasterror) && in_array($typeName, ['E_ERROR', 'E_PARSE', 'E_COMPILE_ERROR', 'E_USER_ERROR'])) {
$payload = [
'text' => "
Error ({$typeName}) | PHP Stopped \n
File ({$file}:{$line}) \n
Message ({$message}) \n",
];
$ch = curl_init(SLACK_WEBHOOK);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
));
$result = curl_exec($ch);
curl_close($ch);
if ($result === false) {
die('Curl error: ' . curl_error($ch));
}
}
}
function common_error_handler($number, $message, $file, $line, $vars)
{
$message = '{"text": "('
. $message
. '). An error (' . $number . ') occurred on line ' . $line . ' and in the file: ' . $file . '."}';
$message = array('payload' => $message);
$c = curl_init(SLACK_WEBHOOK);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_POSTFIELDS, $message);
$r = curl_exec($c);
curl_close($c);
if (($number !== E_NOTICE) && ($number < 2048)) {
die("There was an error. Please try again later.");
}
}
接著
建立一支專門用來發生錯誤的 php file(?!)
<?php
require_once 'common.php';
echo '@test-error.php';
先確認 index.php 運作正常後,再開始讓他發生錯誤 XD
再次修改 index.php,故意讓他出錯
<?php
require_once 'common.php';
echo '@test-error.php';
throw new Exception("my Exception!", 500);
如果 common.php 裡啟用 error_reporting(0);
那畫面上不會有任何錯誤訊息喔~
只要 slack webhook url 和 curl 都正常,就能在 slack 這收到類似下面的訊息~
當然~ 高科技(?) 的工具、服務也是有~
以下三個服務是我比較常用,也有免費方案
(一點點個人感想)
『Slack Bot To Handle PHP Errors Real Time』
https://medium.com/@rajeshjnair/slack-bot-to-handle-php-errors-real-time-d25b3b401b93
Laravel Eloquent whereIn() 每個人都用過,但你曉得但 whereIn() 量大時,可能會造成查詢緩慢問題之一嗎? 他不一定是資料 index 索引的問題,可能是更底層問題喔這邊提供一個 Laravel 資料庫查詢效能優化的手式 Laravel 查詢緩慢的情境 常有的需求是使用指定的 id…
jenkins、circleci、travis 或 Gitlab CI 皆為目前暫知名的 CI/CD 服務,各自缺點也不言而喻...過於肥大、收費略高(?)、速度不夠快執問題...此時使用 go language 開發的 Drone 就出現啦,完全 docker 容器化的運行方式讓整個 CI…
網頁壓縮技術中 gzip 很好用,deflate 己經過時,但你聽過 brotli 嗎? 有著比 gzip 更好、更快的壓縮效率。看起來利大於弊有什麼不用他的理由嗎?簡單從優、缺點來看 brotli!到底 brotli 布羅特利是什麼、如何設定呢。 目前大多的 web server…
為什麼要讓本機使用 Docker 內 PHP? 情境... docker 容器內用的是 PHP 7.4 但你的開發本機還在跑 PHP 5.6 或是更舊,因為 dockerize 的關係會將所有相關環境都轉移到…
為什麼你需要密碼管理工具現代人一天下來需要輸入多少組密碼,工作與生活己經和密碼密不可分! 除了足夠全安的密碼,密碼記錄、儲存的方式又足夠安全嗎?密碼管理工具可以帶來什麼幫助呢? 為什麼你需要密碼管理工具 資安問題!!大多人說著沒做壞事不怕被偷資料、監聽。嚴重曝露出現代人的基本科技素養的低落和無知 🤯 密碼的使用無所不在!! 行動裝置的普及,APP 、手機遊戲、銀行帳戶所有和生活相關的東西都需要密碼!!facebook, line 只要打開 APP 也會輸入密碼只是他是自動輸入、一般情況不可視 (auth token) 一般人最常發生的密碼資安問題…
mysql 資料表分區 mysql table partition 從架構上調整 mysql 的查詢效率。mysql DB 的優化可以簡單也能複雜,除了調整設定值。也可以透過水平分割(Horizontal Partitioning)、垂直分割(Vertical Partitioning) 分庫或分表將資料分散儲存減少資料搜尋、group by 時的效能消耗。拆開批次處理,理論上效率都會變好,本文就水平分割的…