緣起
跟隨上一章的腳步,上一章中,我們主要講解了在用戶發起請求,解析請求,服務器反饋請求以及session的一些知識點,這過程中,難免會遇到一些問題,比方說數據庫查詢失敗,用戶輸入導致腳本出錯,網絡問題等等突發情況,對於突發情況,做過軟件的一般都知道,會有錯誤處理和日志去記錄下這個過程,同樣的,Yii也提供了類似的功能幫助我們去抓住錯誤,記錄錯誤,並且對相應錯誤做出對應處理。
錯誤處理
Yii 內置了一個error handler錯誤處理器。
所有非致命PHP錯誤(如,警告,提示)會轉換成可獲取異常。
拋出異常
use yii\web\NotFoundHttpException; throw new NotFoundHttpException();
對於可能產生異常的地方,我們要使用try...catch...
use Yii; use yii\base\ErrorException; try { 10/0; } catch (ErrorException $e) { Yii::warning("Division by zero."); }
error handler 錯誤處理器默認啟用。
return [ 'components' => [ 'errorHandler' => [ 'errorAction' => 'site/error', ], ] ];
一般的保留原先應用主體中的配置即可,如果想要定制化錯誤的格式輸出,可以去官網好好研究研究呢,這里不細究,錯誤產生,打印出來即可,至於如何記錄下來,方便我們查找,這才是重要的。
日志系統
提起日志系統,大伙可能第一個想到的就是在適當的位置插入一行代碼,然后執行到這行代碼之后就會被記錄一些東西到一個文件中。
是的,這就是最原始的日志系統,之前搞的Python自動發郵件的那個日志記錄系統就是這么簡單的一個玩意兒,但是收到的成效會非常好。就和程序員寫注釋一樣,在對的位置加上log,這會大大降低你系統的維護成本。
Yii提供了一個強大的日志框架,這個框架具有高度的可定制性和可擴展性。
調用起來也相當簡單
Yii::trace():記錄一條消息去跟蹤一段代碼是怎樣運行的。這主要在開發的時候使用。 Yii::info():記錄一條消息來傳達一些有用的信息。 Yii::warning():記錄一個警告消息用來指示一些已經發生的意外。 Yii::error():記錄一個致命的錯誤,這個錯誤應該盡快被檢查。
上面的這幾個日志類型是根據嚴重程度來記錄的
exception需要記錄到warning和error里面
重要的日志信息會單獨記錄到單獨的key中,方便查找,就是這些個方法的第二個參數:category,這個參數是可以自定義的。這和你的配置有關,如下是一個比較標准的配置log的方式。
return [ // the "log" component must be loaded during bootstrapping time 'bootstrap' => ['log'], 'components' => [ 'log' => [ 'targets' => [ [ 'class' => 'yii\log\DbTarget', 'levels' => ['error', 'warning'], ], [ 'class' => 'yii\log\EmailTarget', 'levels' => ['error'], 'categories' => ['yii\db\*'], 'message' => [ 'from' => ['log@example.com'], 'to' => ['admin@example.com', 'developer@example.com'], 'subject' => 'Database errors at example.com', ], ], ], ], ], ];
log
組件必須在 bootstrapping 期間就被加載,以便於它能夠及時調度日志消息到目標里。
上面的error和warning會被以存儲到數據表的形式存儲,我一般都會存儲在runtime的log下面,以文件的方式去存儲,過一周時間備份下這些log,然后從服務器刪除掉這些log。
第二個是error的時候要給admin和developer兩個example.com郵箱發送郵件。
Yii配備了以下的內建日志目標。
yii\log\DbTarget:在數據庫表里存儲日志消息。 yii\log\EmailTarget:發送日志消息到預先指定的郵箱地址。 yii\log\FileTarget:保存日志消息到文件中. yii\log\SyslogTarget:通過調用PHP函數 syslog() 將日志消息保存到系統日志里。
我一般使用的就是那個FileTarget,配置如下:
'log' => [ 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning'], ], [ 'class' => 'yii\log\FileTarget', 'categories' => ['tongzi.info.*', 'yii\db\*'], 'levels' => ['info'], 'logVars' => [], ] ], ]
上面的應用配置設置了 yii\log\Dispatcher::traceLevel 的層級,假如 YII_DEBUG
開啟則是3,否則是0。
這意味着,假如 YII_DEBUG
開啟,每個日志消息在日志消息被記錄的時候, 將被追加最多3個調用堆棧層級;假如 YII_DEBUG
關閉, 那么將沒有調用堆棧信息被包含。
categories 屬性是一個包含消息分類名稱或者模式的數組。
一個分類模式是一個以星號 *
結尾的分類名前綴。假如一個分類名與分類模式具有相同的前綴, 那么該分類名將和分類模式相匹配。
消息的格式
如果你使用了yii\log\FileTarget類的日志目標,你的消息格式應該是下面的~
2014-10-04 18:10:15 [::1][][-][trace][yii\base\Module::getModule] Loading module: debug
默認情況下,日志消息將被格式化,格式化的方式遵循 yii\log\Target::formatMessage():
Timestamp [IP address][User ID][Session ID][Severity Level][Category] Message Text
也可以自定義日志格式,不過完全沒有必要那么搞,這么多的信息足夠查錯啦。
另外,定義好各個category后,你就可以使用各種工具查看log啦。
這邊推薦大家使用兩個日志分析工具,splunk和日志易,splunk,我有個同學在里面,做大數據分析算法,反正我覺得挺牛,Splunk在全球大數據分析首屈一指。而且界面也很友好,只是免費版的只有500M的空間供你使用,這是個巨坑。
還有一個就是日志易啦,也是我目前在用的日志分析工具,國內比較好的工具,大家可以去到他的官網研究搞搞事情,挺不錯的。
好了,今天關於錯誤處理和日志系統相關的就講到這兒^_^