通过SocketLog快速分析OneThink程序

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 通过SocketLog快速分析OneThink程序 http://www.thinkphp.cn/topic/10846.html   浏览:2332 发布日期:2014/02/08 分类:技术分享 正在运行的API有bug,不能var_dump进行调试,因为会影响client的调用。

通过SocketLog快速分析OneThink程序

http://www.thinkphp.cn/topic/10846.html

 
浏览:2332 发布日期:2014/02/08 分类:技术分享
正在运行的API有bug,不能var_dump进行调试,因为会影响client的调用。这时候用SocketLog最好,SocketLog通过websocket将调试日志打印到浏览器的console中。你还可以用它来分析开源程序,分析SQL性能,结合taint分析程序漏洞。 

我将演示如何用SocketLog分析OneThink程序, SocketLog的项目地址: https://github.com/luofei614/SocketLog 

#说明
* SocketLog方便API,AJAX的调试,能将日志通过WebSocket输出到Chrome浏览器的console中
* 它能代替ChromePHP、FirePHP等工具,ChromePHP等是通过header通信,适合AJAX调试,但不适合API调试,而且它们是通过Header通信,Chrome浏览器对传递Header大小有限制,日志如果多了,Chrome浏览器就无法支持。
* 目录结构:
* chrome 目录是 chrome插件的源代码
* chrome.crx 文件是chrome插件的安装包, 目前插件还没有上架到Chrome App Store, 大家需要手动安装, 浏览器地址栏输入并打开: chrome://extensions/ ,然后将chrome.crx拖入即可安装。
* php 目录是php相关脚本。 SocketLog.server.php 是一个 Websocket服务器, SocketLog.class.php是发送日志的类库,我们在发送日志的时候,需要载入这个类库然后调用函数slog即可。
* 效果展示: 我们在浏览网站的时候在浏览器console中就知道程序做了什么,这对于二次开发产品十分有用。 下面效果图在console中打印出浏览discuz程序时,执行了哪些sql语句, 以及执行sql语句的调用栈。程序的warning,notice等错误信息也可以打到console中。



#使用方法
* 首先,请在chrome浏览器上安装好插件。
* 然后,启用Websocket服务, 在命令行中运行 `php php/SocketLog.server.php` , 将会在本地起一个websocket服务 ,监听端口是1229 。 如果想服务后台运行: `nohup php php/SocketLog.server.php > /dev/null &`
* 在自己的程序中发送日志:
  1.        <?php
  2.         include './php/SocketLog.class.php';
  3.         slog('hello world');
  4.         ?>
复制代码
* 用slog函数发送日志, 支持多种日志类型:
  1.         slog('msg','log');  //一般日志
  2.         slog('msg','error'); //错误日志
  3.         slog('msg','info'); //信息日志
  4.         slog('msg','warn'); //警告日志
  5.         slog('msg','trace');// 输入日志同时会打出调用栈
  6.         slog('msg','alert');//将日志以alert方式弹出
  7.         slog('msg','log','color:red;font-size:20px;');//自定义日志的样式,第三个参数为css样式
复制代码
* 通过上面例子可以看出, slog函数支持三个参数:
* 第一个参数是日志内容,日志内容不光能支持字符串哟,大家如果传递数组,对象等一样可以打印到console中。
* 第二个参数是日志类型,可选,如果没有指定日志类型默认类型为log, 第三个参数是自定样式,在这里写上你自定义css样式即可。

##配置
* 在载入SocketLog.class.php文件后,还可以对SocketLog进行一些配置。
* 例如:我们如果想将程序的报错信息页输出到console,可以配置
  1.         <?php
  2.         include './php/SocketLog.class.php';
  3.         slog(array(
  4.         'error_handler'=>true
  5.         ),'set_config');
  6.         echo notice;//制造一个notice报错
  7.         slog('这里是输出的一般日志');
  8.         ?>
复制代码
* 配置SocketLog也是用slog函数, 第一个参数传递配置项的数组,第二个参数设置为set_config
* 还支持其他配置项
  1.         <?php
  2.         include './php/SocketLog.class.php';
  3.         slog(array(
  4.         'host'=>'localhost',//websocket服务器地址,默认localhost
  5.         'port'=>'1229',//websocket服务器端口,默认端口是1229
  6.         'optimize'=>false,//是否显示利于优化的参数,如果运行时间,消耗内存等,默认为false
  7.         'show_included_files'=>false,//是否显示本次程序运行加载了哪些文件,默认为false
  8.         'error_handler'=>false,//是否接管程序错误,将程序错误显示在console中,默认为false
  9.         'force_client_id'=>'',//日志强制记录到配置的client_id,默认为空
  10.         'allow_client_ids'=>array()////限制允许读取日志的client_id,默认为空,表示所有人都可以获得日志。
  11.         )
  12.         ,'set_config');
  13.         ?>
复制代码
* optimize 参数如果设置为true, 可以在日志中看见利于优化参数,如:`[运行时间:0.081346035003662s][吞吐率:12.29req/s][内存消耗:346,910.45kb]` 
* show_included_files 设置为true,能显示出程序运行时加载了哪些文件,比如我们在分析开源程序时,如果不知道模板文件在那里, 往往看一下加载文件列表就知道模板文件在哪里了。
* error_handler 设置为true,能接管报错,将错误信息显示到浏览器console, 在开发程序时notice报错能让我们快速发现bug,但是有些notice报错是不可避免的,如果让他们显示在页面中会影响网页的正常布局,那么就设置error_handler,让它显示在浏览器console中吧。 另外此功能结合php taint也是极佳的。 taint能自动检测出xss,sql注入, 如果只用php taint, 它warning报错只告诉了变量输出的地方,并不知道变量在那里赋值、怎么传递。通过SocketLog, 能看到调用栈,轻松对有问题变量进行跟踪。 更多taint的信息:http://www.laruence.com/2012/02/14/2544.html 
* 设置client_id: 在chrome浏览器中,可以设置插件的Client_ID ,Client_ID是你任意指定的字符串。

* 设置client_id后能实现以下功能:

* 1,配置allow_client_ids 配置项,让指定的浏览器才能获得日志,这样就可以把调试代码带上线。 普通用户访问不会触发调试,不会发送日志。 开发人员访问就能看的调试日志, 这样利于找线上bug。 Client_ID 建议设置为姓名拼命加上随机字符串,这样如果有员工离职可以将其对应的client_id从配置项allow_client_ids中移除。 client_id除了姓名拼音,加上随机字符串的目的,以防别人根据你公司员工姓名猜测出client_id,获取线上的调试日志。
* 设置allow_client_ids示例代码:
  1.         slog(array(
  2.         'allow_client_ids'=>array('luofei_zfH5NbLn','easy_DJq0z80H')
  3.         ),'set_config')
复制代码
* 2, 设置force_client_id配置项,让后台脚本也能输出日志到chrome。 网站有可能用了队列,一些业务逻辑通过后台脚本处理, 如果后台脚本需要调试,你也可以将日志打印到浏览器的console中, 当然后台脚本不和浏览器接触,不知道当前触发程序的是哪个浏览器,所以我们需要强制将日志打印到指定client_id的浏览器上面。 我们在后台脚本中使用SocketLog时设置force_client_id 配置项指定要强制输出浏览器的client_id 即可。
* 示例代码:
  1.         <?php
  2.         include './php/SocketLog.class.php';
  3.         slog(array(
  4.         'force_client_id'=>'luofei_zfH5NbLn'
  5.         ),'set_config');
  6.         slog('test'); `
复制代码
##对数据库进行调试
* SocketLog还能对sql语句进行调试,自动对sql语句进行explain分析,显示出有性能问题的sql语句。 如下图所示。 

* 图中显示出了三条sql语句 , 第一条sql语句字体较大,是因为它又性能问题, 在sql语句的后台已经标注Using filesort。 我们还可以点击某个sql语句看到sql执行的调用栈,清楚的知道sql语句是如何被执行的,方便我们分析程序、方便做开源程序的二次开发。图中第三条sql语句为被点开的状态。
* 用slog函数打印sql语句是,第二个参数传递为mysql或mysqli的对象即可。 示例代码:
  1.         $link=mysql_connect( 'localhost:3306' , 'root' , '123456' , true ) ;
  2.         mysql_select_db('kuaijianli',$link);
  3.         $sql="SELECT * FROM `user`";
  4.         slog($sql,$link);
复制代码
后面会以OneThink为实例再对数据库调试进行演示。

* 注意,有时候在数据比较少的情况下,mysql查询不会使用索引,explain也会提示Using filesort等性能问题, 其实这时候并不是真正有性能问题, 你需要自行进行判断,或者增加更多的数据再测试。

##对API进行调试
网站调用了API ,如何将API程序的调试信息也打印到浏览器的console中? 前面我们讲了一个配置 force_client_id, 能将日志强制记录到指定的浏览器。 用这种方式也可以将API的调试信息打印到console中,但是force_client_id 只能指定一个client_id, 如果我们的开发环境是多人共用,这种方式就不方便了。
其实只要将浏览器传递给网站的User-Agent 再传递给API, API程序中不用配置force_client_id, 也能识别当前访问程序的浏览器, 将日志打印到当前访问程序的浏览器, 我们需要将SDK代码稍微做一下修改。 调用API的SDK,一般是用curl写的,增加下面代码可以将浏览器的User-Agent传递到API 。 
  1.         $headers=array(
  2.                 'User-Agent: '.$_SERVER['HTTP_USER_AGENT']
  3.             );
  4.         curl_setopt($ch,CURLOPT_HTTPHEADER,$headers); 
复制代码
##分析开源程序

有了SocketLog,我们能很方便的分析开源程序,下面以OneThink为例, 大家可以在 http://www.onethink.cn/ 下载最新的OneThink程序。 安装好OneThink后,按下面步骤增加SocketLog程序。 

* 将SocketLog.class.php复制到OneThink的程序目录中,你如果没有想好将文件放到哪个子文件夹,暂且放到根目录吧。 
* 编辑入口文件index.php, 再代码的最前面加载SocketLog.class.php ,并设置SocketLog

  1.         <?php
  2.             include './SocketLog.class.php';
  3.             slog(array(
  4.              'error_handler'=>true,
  5.              'optimize'=>true,
  6.              'show_included_files'=>true
  7.             ),'set_config');
复制代码
- 编辑ThinkPHP/Library/Think/Db/Driver/Mysqli.class.php 文件, 如果你用的数据库驱动类型不是mysqli,而是mysql,那么请打开Mysql.class.php, 找到执行sql语句的地方, 这个类中得execute 方法为一个执行sql语句的方法,大约在119行处,增加代码:
  1.         slog($this->queryStr,$this->_linkID);
复制代码
- 类中的query方法也是一个执行sql语句的地方, 同样需要增加上面的代码, 大约在92行增加slog($this->queryStr,$this->_linkID);

- 然后浏览网站看看效果: 


通过console的日志,访问每一页我们都知道程序干了什么,是一件很爽的事情。

- 提示:另一种更简单的方法,因为OneThink每次执行完sql语句都会调用$this->debug, 所以我们可以把slog($this->queryStr,$this->_linkID); 直接写在 Db.class.php文件的debug方法中。 这样不管是mysqli还是mysql驱动都有效。

##About Me
Author: @luofei614 新浪微博: http://weibo.com/luofei614
快简历CTO,ThinkPHP核心开发者之一,待过新浪云计算
如果你觉得SocketLog对你有帮助, 以后找工作就用快简历吧: http://rd.kuaijianli.com

附件 socketlog.zip ( 71.83 KB 下载:34 次 )

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3月前
|
监控
LabVIEW程序内存泄漏分析与解决方案
LabVIEW程序内存泄漏分析与解决方案
120 0
|
5月前
|
存储 编解码 Windows
LabVIEW程序代码更新缓慢
LabVIEW程序代码更新缓慢
57 1
|
5月前
|
存储 开发工具 数据库
认识HIS系统 HIS系统的主要功能解释说明
HIS系统即医院信息系统(全称为Hospital information System) ,是指利用计算机软硬件技术和网络通信技术等现代化手段,对医院及其所属各部门的人流、物流、财流进行综合管理,对在医疗活动各阶段产生的数据进行采集、存储、处理、提取、传输、汇总,加工形成各种信息,从而为医院的整体运行提供全面的自动化管理及各种服务的信息系统。
395 5
labview把实时数据写入excel的程序的思路
labview把实时数据写入excel的程序的思路
151 0
|
Web App开发 JavaScript IDE
如何直观地理解程序的运行过程?
了解代码的执行过程是编程的基本要求。一个熟练的编程老手只需要用肉眼看着代码,就能对其运行的过程有所了解。然而对于刚接触编程不久的新手来说,这种事情就没那么显而易见了。于是在编写代码和调试代码时,一旦程序的逻辑有些复杂,就像掉进代码的迷宫,完全不知道东南西北。
|
存储 自然语言处理 编译器
程序的编译与链接(C语言为例) #代码写好后到运行期间要经过怎样的过程呢?# 粗略版 #
程序的编译与链接(C语言为例) #代码写好后到运行期间要经过怎样的过程呢?# 粗略版 #
|
小程序 前端开发 API
小程序中实现获取全部数据
小程序中实现获取全 部数据
小程序中实现获取全部数据
|
存储 小程序 数据管理
小程序中的统计分析功能
小程序中的统计分析功能
小程序中的统计分析功能
|
存储 小程序 容器
小程序中实现文章的关注功能
小程序中实现文章的关注功能
小程序中实现文章的关注功能
段错误(核心已转储)问题的分析方法(未成功)
段错误(核心已转储)问题的分析方法(未成功)
251 0