thinkphp mysql 日志_基于thinkphp实现异常日志详细统计功能
后端的代碼基于thinkphp框架開發(fā),隨著業(yè)務(wù)的增加,代碼復(fù)雜度不斷增多,而且有好幾份代碼,可能部署在不同的服務(wù)器上。即使在測試服務(wù)器上經(jīng)過嚴(yán)格測試,正式環(huán)境有時也很難避免出現(xiàn)bug,所以需要較為詳細(xì)的日志來記錄,而且日志要有統(tǒng)一的位置存放。
1.thinkphp本身的異常處理
稍微熟悉thinkphp的都應(yīng)該知道,它的異常可以自己定義,只要自定定一個handle類,繼承think\exception\handle,然后重寫里面的render方法,然后在配置文件配置自己定義的異常處理類,就可以根據(jù)業(yè)務(wù)場景的不同,以不同的形式輸出異常信息,比如json、html。所以一個工程中是存在多個think\exception\handle的子類的。對應(yīng)異常信息的記錄,其實tp本身是有記錄的。
think\Error類異常處理的代碼如下。
/**
* Exception Handler
* @access public
* @param \Exception|\Throwable $e
*/
public static function appException($e)
{
if (!$e instanceof \Exception) {
$e = new ThrowableError($e);
}
self::getExceptionHandler()->report($e);
if (PHP_SAPI == 'cli') {
self::getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
} else {
self::getExceptionHandler()->render($e)->send();
}
}
public static function appError($errno, $errstr, $errfile = '', $errline = 0)
{
$exception = new ErrorException($errno, $errstr, $errfile, $errline);
if (error_reporting() & $errno) {
// 將錯誤信息托管至 think\exception\ErrorException
throw $exception;
}
self::getExceptionHandler()->report($exception);
}
其中self::getException()就是根據(jù)配置獲取處理異常的handle實例,然后調(diào)用了該實例的report方法。所以report方法是所有異常必經(jīng)之路。經(jīng)過report處理以后,才會根據(jù)php當(dāng)前運(yùn)行模式進(jìn)行渲染輸出。
2.thinkphp異常記錄的不足
點(diǎn)擊report跳轉(zhuǎn)到think\exception\handle
public function report(Exception $exception)
{
if (!$this->isIgnoreReport($exception)) {
// 收集異常數(shù)據(jù)
if (Container::get('app')->isDebug()) {
$data = [
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'message' => $this->getMessage($exception),
'code' => $this->getCode($exception),
];
$log = "[{$data['code']}]{$data['message']}[{$data['file']}:{$data['line']}]";
} else {
$data = [
'code' => $this->getCode($exception),
'message' => $this->getMessage($exception),
];
$log = "[{$data['code']}]{$data['message']}";
}
if (Container::get('app')->config('log.record_trace')) {
$log .= "\r\n" . $exception->getTraceAsString();
}
Container::get('log')->record($log, 'error');
}
}
可以看到這是thinkphp默認(rèn)的異常記錄,缺點(diǎn)如下:
記錄的信息不夠詳情,僅僅記錄了異常信息,沒有記錄訪問的url、參數(shù)、用戶id和其他相關(guān)的信息,對想要更快速的定位異常信息,提供的依據(jù)較少。
日志記錄是記錄在文件的,放在了runtime下的log目錄,按照日期劃分,但是這些文件是有大小和個數(shù)限制的。超過了就會合并、改名字、刪除。對于需要快速查找日志信息,有的時候不方便,還有可能找不到。
對于多服務(wù)器部署來說、每個工程下面的日志文件是獨(dú)立的、沒有一個統(tǒng)一的地方去查看這些日志,需要一個工程一個工程去查找日志,非常麻煩。
不利于對每天的日志進(jìn)行分析,統(tǒng)計。
3.我們?nèi)绾胃倪M(jìn)
所以我們要強(qiáng)化日志記錄功能,因為report方法是tp記錄日志的方法,所以顯然我們定義一個baseHandle繼承 think\exception\handle,然后在baseHandle重寫report方法就可以了,然后工程中所有的handle都繼承baseHandle,異常自然就會被自定義的report方法里面邏輯處理。到底記錄這些異常信息,有很多方案。這里我們用的是mongo存儲,盡可能詳情的記錄。無論如何,把數(shù)據(jù)都記錄在一塊了,然后后臺增加個查看異常信息的功能,幸福還會遠(yuǎn)嗎?
class BaseHandle extends parentHandle
{
public function report(Exception $exception)
{
parent::report($exception); // TODO: Change the autogenerated stub
try{
// //記錄日志
$exceptionLogParam = new ExceptionLogParam();
$exceptionLogParam->exception = $exception->getMessage();
$exceptionLogParam->trace = $exception->getTraceAsString();
$exceptionLogParam->is_cli = PHP_SAPI == 'cli' ? 1 : 0;
$exceptionLogParam->header = \GuzzleHttp\json_encode(Request::header(), JSON_UNESCAPED_UNICODE);
$exceptionLogParam->param = \GuzzleHttp\json_encode(Request::param(), JSON_UNESCAPED_UNICODE);
$exceptionLogParam->method = \GuzzleHttp\json_encode(Request::method(), JSON_UNESCAPED_UNICODE);
$exceptionLogParam->controller = Loader::parseName(Request::controller(), 0);
$exceptionLogParam->param = Request::param();
$exceptionLogParam->param = \GuzzleHttp\json_encode($exceptionLogParam->param, JSON_UNESCAPED_UNICODE);
$exceptionLogParam->action = Request::action();
$exceptionLogParam->module = Request::module();
$exceptionLogParam->user_id = RememberMeHelper::$_userId;
$exceptionLogParam->created_at = time();
$exceptionLogParam->cookie = \GuzzleHttp\json_encode(Request::cookie(),true);
$exceptionLogParam->session = \GuzzleHttp\json_encode(Request::session(),true);
$exceptionLogParam->url = Request::url();
$exceptionLogParam->server_ip = get_server_ip();
$exceptionLogParam->file_line_info = $exception->getFile().$exception->getLine();
ExceptionLogService::getInstance()->create($exceptionLogParam);
}catch (\Exception $exception){
\think\facade\Log::write('存儲日志發(fā)生了異常');
}
}
}
考慮過的其他存儲方法:
數(shù)據(jù)庫建立一個exception表專門存儲,因為異常信息量可能非常大,用mysql存儲代價比較昂貴,而且對mysql的讀寫性能感覺會有干擾,所以放棄。
用一個專門的mongo數(shù)據(jù)庫存儲,因為thinkphp的model是可以配置的,只要配置連接數(shù)據(jù)庫是mongo,使用起來沒有什么區(qū)別。mongo便宜一些,日志存的多,查詢方式比較單一,所以選了這個。
考慮過ELK,往ES里面寫入文檔,了解過網(wǎng)上有很多說可以用ELK做日志分析,但是對這個目前使用不熟悉,以后考慮研究下。
總結(jié)
以上是生活随笔為你收集整理的thinkphp mysql 日志_基于thinkphp实现异常日志详细统计功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用BURP时,ca证书已经安装,谷歌浏
- 下一篇: PLSQL基本操作手册