后端的代码基于thinkphp框架开发,随着业务的增加,代码复杂度不断增多,而且有好几份代码,可能部署在不同的服务器上。即使在测试服务器上经过严格测试,正式环境有时也很难避免出现bug,所以需要较为详细的日志来记录,而且日志要有统一的位置存放。

1.thinkphp本身的异常处理

稍微熟悉thinkphp的都应该知道,它的异常可以自己定义,只要自定定一个handle类,继承think\exception\handle,然后重写里面的render方法,然后在配置文件配置自己定义的异常处理类,就可以根据业务场景的不同,以不同的形式输出异常信息,比如json、html。所以一个工程中是存在多个think\exception\handle的子类的。对应异常信息的记录,其实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()就是根据配置获取处理异常的handle实例,然后调用了该实例的report方法。所以report方法是所有异常必经之路。经过report处理以后,才会根据php当前运行模式进行渲染输出。

2.thinkphp异常记录的不足

点击report跳转到think\exception\handle

public function report(Exception $exception)

{

if (!$this->isIgnoreReport($exception)) {

// 收集异常数据

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默认的异常记录,缺点如下:

记录的信息不够详情,仅仅记录了异常信息,没有记录访问的url、参数、用户id和其他相关的信息,对想要更快速的定位异常信息,提供的依据较少。

日志记录是记录在文件的,放在了runtime下的log目录,按照日期划分,但是这些文件是有大小和个数限制的。超过了就会合并、改名字、删除。对于需要快速查找日志信息,有的时候不方便,还有可能找不到。

对于多服务器部署来说、每个工程下面的日志文件是独立的、没有一个统一的地方去查看这些日志,需要一个工程一个工程去查找日志,非常麻烦。

不利于对每天的日志进行分析,统计。

3.我们如何改进

所以我们要强化日志记录功能,因为report方法是tp记录日志的方法,所以显然我们定义一个baseHandle继承 think\exception\handle,然后在baseHandle重写report方法就可以了,然后工程中所有的handle都继承baseHandle,异常自然就会被自定义的report方法里面逻辑处理。到底记录这些异常信息,有很多方案。这里我们用的是mongo存储,尽可能详情的记录。无论如何,把数据都记录在一块了,然后后台增加个查看异常信息的功能,幸福还会远吗?

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('存储日志发生了异常');

}

}

}

考虑过的其他存储方法:

数据库建立一个exception表专门存储,因为异常信息量可能非常大,用mysql存储代价比较昂贵,而且对mysql的读写性能感觉会有干扰,所以放弃。

用一个专门的mongo数据库存储,因为thinkphp的model是可以配置的,只要配置连接数据库是mongo,使用起来没有什么区别。mongo便宜一些,日志存的多,查询方式比较单一,所以选了这个。

考虑过ELK,往ES里面写入文档,了解过网上有很多说可以用ELK做日志分析,但是对这个目前使用不熟悉,以后考虑研究下。

thinkphp mysql 日志_基于thinkphp实现异常日志详细统计功能相关推荐

  1. java 统一日志_基于log4j实现统一日志管理

    背景: 一般操作系统级的告警有相关的软件,但我们应用级日志往往无法统一监控.分析.因为最近的项目是比较大的一个平台,有七.八个子系统,weblogic域也有三.四个.如果用户自身能够实时监控到应用级致 ...

  2. JAVA基于Slack实现异常日志报警

    一.功能介绍 在我们日常开发中,如果系统在线上环境上,发生异常,开发人员不能及时知晓来修复,可能会造成重大的损失,因此后端服务中加入异常报警的功能是十分必要的,而开发一个功能全面的异常报警服务,可能会 ...

  3. php源码 拼车网顺风车_基于ThinkPHP框架开发的在线微信拼车系统完整PHP源码+支付微信支付...

    源码介绍 基于ThinkPHP框架开发的在线微信拼车系统主要是基于微信的在线拼车系统,也是一款不错的微信号管理系统,该微信拼车系统主要是基于ThinkPHP3.2.3框架开发,主要功能有发布租车信息. ...

  4. thinkphp删除某一学生_基于ThinkPHP实现批量删除

    本文实例分析了基于ThinkPHP实现批量删除的代码实例,分享给大家供大家参考,具体如下: 废话不多说,先上效果图: HTML布局(基于bootstrap) 留言列表 返回 删除 id名称邮箱内容日期 ...

  5. php 微信分享功能_基于thinkPHP实现的微信自定义分享功能

    这篇文章主要介绍了基于thinkPHP实现的微信自定义分享功能,结合实例形式分析了thinkPHP调用微信接口实现自定义分享功能的相关操作技巧,需要的朋友可以参考下 本文实例讲述了基于thinkPHP ...

  6. 节点图一般的比例_基于图的异常检测(二):LOCKINFER

    论文:Inferring lockstep behavior from connectivity pattern in large graphs 作者:Meng Jiang,Peng Cui 来源:P ...

  7. 怎样用java编写日志_用JAVA写一个日志类程序以供大家学习

    中华网络安全联盟    作者:jacoo    来源:本站原创    时间:2006-4-18 说明: 尽管JAVA类库和其他工具提供了不少的纪录程序运行状态的日志类,我发觉也 不是万能的,有时需要根 ...

  8. java消费者模式_基于Java 生产者消费者模式(详细分析)

    生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...

  9. python点名代码_基于python tkinter的点名小程序功能的实例代码

    基于python tkinter的点名小程序功能的实例代码,花名册,次数,窗口,未找到,初始化 基于python tkinter的点名小程序功能的实例代码 易采站长站,站长之家为您整理了基于pytho ...

最新文章

  1. java图片16帧动画_Java实现帧动画的实例代码
  2. Kafka 常见命令行 Version 2.1.0
  3. P3338 [ZJOI2014]力 FFT + 推式子
  4. undefined reference to `std::ios_base::Init::Init() 解决
  5. CrystalMaker 10.6.2 mac版 CrystalMaker X最新版
  6. 软件项目管理四个核心价值观
  7. python科学坐标系绘制分析_Python电子教案9-1-科学计算和可视化.ppt
  8. python字符串转整数_Python连接字符串和整数
  9. 直线插补计算过程_【计鹏视角】风速数据插补对发电量的影响
  10. opensuse 安装 Anaconda3 之后出现Could not start d-bus. Can you call qdbus?
  11. 【路径规划】基于遗传算法求解同时取送货车辆路径问题matlab代码
  12. BatchOutput PDF 2.2.32 Mac 破解版 PDF文档自动批量打印工具
  13. Postgresql临时表
  14. 计算机类毕业设计评阅书评语,本科毕业论文评阅人评语_毕业论文评阅人评语模板文库_本科毕业论文评阅老师评语大全...
  15. win8 cn_windows_8_x86_dvd_915414.iso 安装密钥
  16. 4核处理器_最新版的MAC mini配M1处理器你会买吗?
  17. postgresql 12.0 源码编译安装
  18. Jetpack Compose——Icon(图标)的使用
  19. Android 解压zip文件你知道多少?
  20. vim插入模式小技巧

热门文章

  1. verilog设计简易正弦波信号发生器_信号发生器入门手册-白皮书 (上)
  2. 目前最全的IT技术问答、社区、科技服务网站合集
  3. 全球及中国柔性AMOLED面板行业消费量调研及投资前景预测报告2022-2028年
  4. 陈远:兴趣是永远的老师
  5. serverless入门介绍
  6. 给信号添加高斯白噪声
  7. 一张图,了解网站SEO方案
  8. msi和exe安装文件有什么区别
  9. 北京筑龙CTO吴英礼受邀在清华大学互联网产业研究院做分享
  10. 第十二届蓝桥杯省赛一等奖国赛一等奖经验总结