日誌記錄
- 日誌配置
application/config.php
'log' => [
// 日誌記錄方式,內置 file socket 支持擴展
'type' => 'File',
// 日誌保存目錄
'path' => LOG_PATH,
// 日誌記錄級別
'level' => ['error','notice','debug','sql'],
],
-
日誌關閉的方式
- 設置日誌類型爲
test
- 設置日誌記錄級別
- 設置日誌類型爲
-
日誌級別
- log 常規日誌,用於記錄日誌
- error 錯誤,一般會導致程序的終止
- notice 警告,程序可以運行但是還不夠完美的錯誤
- info 信息,程序輸出信息
- debug 調試,用於調試信息
- sql SQL語句,用於SQL記錄,只在數據庫的調試模式開啓時有效
-
記錄日誌的幾種方式
- Log::write(‘message’,‘info’),實時寫入一條日誌信息
- Log::record(‘message’,‘info’),寫到內存中,等系統請求結束後會自動寫入
- trace(‘message’,‘info’)
- 在應用日誌配置關閉的情況下:Log::init()進行手動記錄
在開發環境可以通過打印變量和調試來發現錯誤並糾正,但是如果在生產環境中是不允許隨意修改來調試錯誤,
只有等到新版本系統出來才能去改動生產環境的代碼,生產環境通過日誌(最好的方法)來排查錯誤。
很多信息如果都作爲日誌去記錄,則會出現很多無意義的記錄信息,不僅耗費了很大的硬盤內存資源,同時也影響了錯誤的排查。
TP5默認會記錄全部(即使你設置了配置項level),需要手動關閉,然後有選擇的來記錄日誌。
- 自定義全局日誌記錄
//首先關閉系統日誌記錄配置,然後再入口文件最下面添加如下代碼
\think\Log::init([
'type' => 'File',
'path' => LOG_PATH,
'level' => ['error']
]);
//然後再想要記錄日誌的地方寫入日誌即可
Log::record('message','error');
//如果使用的是write方法,則記錄的會有其他信息,這是我們不希望的,不便於調試
錯誤和調試
- 開啓調試模式
app_debug = true
- 變量調試
- dump
- halt
- 性能調試
開發過程中,有些時候爲了測試性能,經常需要調試某段代碼的運行時間或者內存佔用開銷
- 使用
Debug
類
Debug::remark('begin'); // ...其他代碼段 Debug::remark('end'); // ...也許這裏還有其他代碼 // 進行統計區間 echo Debug::getRangeTime('begin','end').'s';
- 使用助手函數
debug
debug('begin'); // ...其他代碼段 debug('end'); // ...也許這裏還有其他代碼 // 進行統計區間 echo debug('begin','end').'s'; echo debug('begin','end',6).'s'; echo debug('begin','end','m').'kb';
- 使用
- sql調試的三種方式
- 日誌方式
- 監聽SQL
- getLastSql或者fetchSql
拋出異常
異常的分類可以分爲由於客戶端行爲導致的異常和服務器自身的異常。
客戶端行爲導致的異常,通常不需要記錄日誌,需要向客戶端返回具體信息。比如沒有通過驗證器,沒有查詢到結果
服務器自身的異常,通常需要記錄日誌,不需要向客戶端返回具體的錯誤信息,即使返回,客戶端也有可能看不懂,或者不關心,
但可以返回通用錯誤信息。
代碼越抽象,複用性越高;封裝性越好,適應代碼變化的能力就越強
-
自定義公共異常類
namespace app\lib\exception; use think\Exception; class BaseException extends Exception { public $code = 400; public $msg = 'invalid parameters'; public $errorCode = '999'; public $shouldToClient = true; public function __construct($params = []) { if( ! is_array($params)) return; if( array_key_exists('code',$params) ) $this->code = $params['code']; if( array_key_exists('msg',$params) ) $this->code = $params['msg']; if( array_key_exists('errorCode',$params) ) $this->code = $params['errorCode']; } }
-
自定義公共異常類子類
namespace app\lib\exception; class MissException extends BaseException { public $code = 404; public $msg = 'global:your required resource are not found'; public $errorCode = 10001; }
-
自定義異常處理類
namespace app\lib\exception;
use Exception;
use think\exception\Handle;
use think\Log;
use think\Request;
class ExceptionHandler extends Handle
{
private $code;
private $msg;
private $errorCode;
public function render(Exception $e)
{
//如果是自定義異常,則控制http狀態碼,不需要記錄日誌
//因爲這些通常是因爲客戶端傳遞參數錯誤或者是用戶請求造成的異常
//不應當記錄日誌
if( $e instanceof BaseException ){
$this->code = $e->code;
$this->msg = $e->msg;
$this->errorCode = $e->errorCode;
}else{
// 如果是服務器未處理的異常,將http狀態碼設置爲500,並記錄日誌
// 調試狀態下需要顯示TP默認的異常頁面,因爲TP的默認頁面
// 很容易看出問題
if( config('app_debug') ){
return parent::render($e);
}
$this->code = 500;
$this->msg = 'sorry,we make a mistake. (^o^)Y';
$this->errorCode = 999;
$this->recordErrorLog($e);
}
$request = Request::instance();
$result = [
'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => $request = $request->url()
];
return json($result, $this->code);
}
/**
* 記錄異常日誌
* @param Exception $e
*/
private function recordErrorLog(Exception $e)
{
Log::init([
'type' => 'File',
'path' => LOG_PATH,
'level' => ['error']
]);
Log::record($e->getMessage(),'error');
}
}