日志记录
- 日志配置
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');
}
}