錯誤追蹤、回報非常重要,看到的錯誤才知道怎麼修。
現今 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
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 時的效能消耗。拆開批次處理,理論上效率都會變好,本文就水平分割的…
透過 vscode Debug 利用中斷點 (breakpoints) 讓開發、偵錯更聰明。 加快除錯速度,而不是用傳統的 console log 方式查看變數、物件內容找問題。 本篇教你如何用 vscode + node +…