很好用的php在线调试工具

       什么叫在线调试?就是在线上生产环境进行调试,假设有一天用户报某个页面某个数据怎么不对啊,看来线上出BUG了,你要迅速找出原因,首先看日志,可悲剧的是没有足够的日志让你确定BUG的原因,也许你这时想看某个PHP变量的值,可是如果直接在线上加代码调试,风险极大,不可行,如果用线下环境,可是数据环境不同,可能难以复现线上的BUG呢,这个php在线调试工具就是为解决这种问题而生,可以让你方便地查看任意线上PHP变量的值而不用改动代码,就像C的调试工具gdb那样,以下叫它ydb。它还有不少其它功能,所有功能参见本文目录。

       ydb采用扩展实现,在url中输入相关调试参数,即可查看相关变量值,参数包括类名,函数名,变量名等。ydb不但可以让你查看任意变量值,而且可以查看函数执行耗时情况,也就是不但可以用来排除业务逻辑BUG,也可以用查看性能问题。你也许担心一个扩展放在线上是否会影响性能,它实际上对性能的影响很小,相关额外计算都是调试者本身发的请求产生,如果你觉得很小的性能影响也不能容忍,那可以在调试时才加上该扩展,重启下php进程即可。

     下面来看看ydb的具体使用

     假设有如下代码在index.php中是我们的调试对象

<?php


class CB  {
	private $pv = 'abc';
	function add($a,$b){
		 return $a+$b;
	}
}

class CA {

	public function look_value($pa,$pb){
		$fa = $pa;
		$fb = $pb;
		$fc = $fa+$fb;
       
		$arr = array(1,2,3);
		$objCb = new CB();
		$fd = $objCb->add(3,4);
 
		$arr = array(4,5,6);
		return $fd;
	}
	
	function look_cost(){
		$this->fun1();
		$this->fun2();
		$this->fun3();
		usleep(300000);
		
	}
	
	function fun1(){
		usleep(100000);
		return;
	}
	function fun2(){
		usleep(200000);
		return;
	}
	
	function fun3(){
		usleep(500000);
		return;
	}
}


$objAt = new CA();

$res = $objAt->look_value(1, 2);
$res = $objAt->look_cost();

echo "should not be here";


一. 查看变量值

假设我们要查看类CA函数look_value中变量arr的值
我们需要在浏览器中输入如下url: http://php.wenda.so.com/index.php?c=CA&f=look_value&v=arr ,
各参数意义如下
c : 表示类名
f : 表示函数名
v: 表示你想查看的变量名

键入url的结果是


     从结果可以看出值是arr第二次的赋值,所以ydb的显示值都是函数执行完毕变量最后的值(什么?你想看中间值,以后会有的)。

     另外,如果不输入v参数,则会打印出函数中的所有变量,输入http://php.wenda.so.com/index.php?c=CA&f=look_value的结果如下所示

     

       可以看到函数look_value中的所有变量包括参数及对象的值都打印出来了

      上面说的是get请求,如果是post请求,那该怎么办呢?同样是在url中输入参数,该 url打开提交的表单,在提交表单时,即可打印相应变量值,不过加上参数o标识这是一个post表单请求,这样就不会在当前请求中进行变量打印了。打开url: http://php.wenda.so.com/post.html?c=CA&f=look_value&o=1,显示表单:

      

      点提交按钮后,同样打印类函数look_value中的值,与get请求中一样,如下图所示

      

      扩展中即通过读取post请求的refer值来实现变量值打印。

      有时你不想把相关值显示在浏览器上而影响页面的正常展示,而想打印在日志文件中,这时你可以在url中添加l=1参数即可将相关变量输出打印在日志文件中,日志文件是log/ydbinfo.log,在php安装根目录中。


二. 查看执行耗时

      ydb可以查看某个函数中所有执行子函数的从高到低的执行耗时排行以及该函数执行的总耗时,通过一个个函数跟踪下去,就很容易找出系统的瓶颈在哪,到底哪个函数执行花费了最长时间。
      查看执行耗时,也要输入 c,f参数,表示要查看哪个类的哪个函数的耗时情况,另外需要加上t=1参数,表示是查看耗时,而不是查看变量值。继续使用之前index.php中的代码,输入url :  http://php.wenda.so.com/index.php?c=CA&f=look_cost&t=1,即可看到如下结果

     

      最上面一行表示look_cost总的耗时,接下来是look_cost中调用的三个函数耗时从大到小的耗时排行,在实际情况中,我们可以进一步将f参数改为耗时最大的那个子函数,一步步跟踪找到系统瓶颈所在。

      对于post请求以及打印信息到日志中,查看耗时与查看变量值一样,相应使用o,l参数即可。


三. 更改运行时变量值-强大的单元测试工具

          有时我们会遇到这种情况,某用户显示的私有数据是错误的,而开发人员无法登录用户账号进行查看,我们需要知道用户展示的数据到底是什么以确定原因。ydb能够对运行时变量值进行更改,我们可以将相关函数的参数改为相应用户的,这样就能看他的私有数据了。
          将index.php修改如下:
<?php


class CB  {
	private $pv = 'abc';
	function add($a,$b){
		 return $a+$b;
	}
}

class CA {

	public function look_value($pa,$pb,$arr){
		$pa = 8;
		$fa = $pa;
		$fb = $pb;
		$fc = $fa+$fb;
       
		$arr = array(1,2,3);
		$objCb = new CB();
		$fd = $objCb->add(3,4);
 
		$arr = array(4,5,6);
		return $fd;
	}
	
	function look_cost(){
		$this->fun1();
		$this->fun2();
		$this->fun3();
		usleep(300000);
		
	}
	
	function fun1(){
		usleep(100000);
		return;
	}
	function fun2(){
		usleep(200000);
		return;
	}
	
	function fun3(){
		usleep(500000);
		return;
	}
}


$objAt = new CA();

$arr = array('aa' => 'vvv' ,'bb' =>123);
$res = $objAt->look_value(1, 2,$arr);
$res = $objAt->look_cost();

echo "should not be here";
         新变量值在名为a的url参数中输入,假如有如下输入参数  http://php.wenda.so.com/index.php?c=CA&f=look_value&a={pa=3:pb=4},即可看到如下结果:


"the replace variable list" 表示相应变量替换前后的值,url 中 a={pa=3:pb=4} 表示pa,pb用新的变量值覆盖代码中原始传入的值,我们可以输入任意多个值,但只有被覆盖的变量是存在的才会有效,同时函数中有对变量重新赋值,则采用新值,因为 变量值替换是在函数开始执行之前进行的,如pa的值是8,pb变成了新值4。各参数用冒号分开。覆盖代码中的变量值当然也必须是针对某个类的某个函数中的,所以不能确少c,f参数。 

有时我们函数中的某个变量是数组,ydb同样可以对数组变量值进行覆盖。如下url   http://php.wenda.so.com/index.php?c=CA&f=look_value&a={pa=3:pb=4:arr[abc]=123} 显示如下:

实际上我们可以在a参数构建自己想要的任意复杂多层次的数组,而不管之前是什么形式的数组,甚至可以将pa这样不是数组的变量覆盖为数组变量,反之,我们也可以将原来是数组的变量覆盖为普通非数组变量。

一般情况下,我们只需要覆盖函数的输入参数,这样我们就可以很方便地对函数进行单元测试了。经常我们只改动了某个函数的一小段代码,也就只需要验证它的正确性即可,我们可以使用ydb通过覆盖各种参数组合对它进行单元测试,在浏览器页面操作中可能很难构造各种特殊输入参数的情况,人为可以定制参数是很方便的。

另外基于这种变量覆盖功能,我们可以建立一个强大的单元测试框架,测试数据都通过url中的a参数进行输入。这个单元测试框架是和语言无关,因为它与被测试对象是通过HTTP协议交互的,这样我们可以用其它语言写单元测试客户端对PHP代码进行单元测试。同样地,我们可以用统一的单元测试客户端对多种语言的项目进行测试,只要被测试的对象是支持类似 ydb这种HTTP协议的交互方式的。


四. 跨网络的调试工具

 现在大型网站内部一般按功能划分为多个模块(或说子系统),一些底层模块常作为一个服务对外提供HTTP接口,各模块可能部署在不同的机器集群中,并通过HTTP协议交互,这是典型的SOA架构。

而ydb是支持跨网络调试的,假设我们的浏览器请求首先到了A模块,而A模块通过HTTP协议调用了B模块,之前描述的所有调试功能都能在B模块中使用。我们可以在url中输入B模块的类名,函数名即可查其它变量值或是耗时排行。当然假设B模块又调用了C 模块,我们同样可以对C模块进行调试,只要相应的模块装上了ydb扩展,ydb目前只支持HTTP协议的网络调用。

假设有如下客户端代码rpcclient.php,服务端代码是之前的index.php
<?php
$url = "http://127.0.0.1/index.php";
$host="php.wenda.so.com";


$ch = curl_init($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('host:'.$host));
$res = curl_exec($ch);

//print_r($res);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('host:'.$host));
$res = curl_exec($ch);
//print_r($res);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('host:'.$host));
$res = curl_exec($ch);
在浏览器键入url php.wenda.so.com/rpcclient.php?c=CA&f=look_value&v=arr,结果如下

即可看到其返回了服务端代码返回的相应变量值,与调试直接调用的模块效果是一样的,这对于一些后端模块维护者来说是很方便的。

五.网络调用性能分析

之前所描述的查看耗时排行功能是针对某一个函数内部执行来说的,但一般我们更关心某个模块对外接口调用耗时的情况,ydb能够将某个请求在一个模块中所有对外网络请求的耗时显示出来并进行排序,并且对同一url请求进行累加计数,只要在参数中输入r参数即可。

在浏览器中输入url php.wenda.so.com/rpcclient.php?r=1,显示结果如下:

通过这样的功能,我们很快就能知道到底是哪个外部接口调用耗费了最长的时间,目前ydb只支持对HTTP协议接口调用耗时情况的显示,未来考虑对mysql,redis,memcache等常用的其它网络调用的支持。

六.dump代码到页面

这是其中的小功能,你可以在url中加上s参数将相应函数的代码dump到页面上,这让你在分析变量值的情况时不用去其它地方看代码。在浏览器键入如下url
http://php.wenda.so.com/index.php?c=CA&f=look_value&s=1 显示结果如下:




是不是跟gdb有点像了,在看变量值的时候同样可以看代码。ydb还有更多强大的功能已在计划中,它只会比gdb更好用,它的最终目标是一个系统出了任何问题只需要在url中简单敲入参数就可以将其以直观方式显示到页面上。

      该扩展已放在github 上 https://github.com/micweaver/ydb,ydb支持php5.2及以上版本,将Makefile中的php源码路径改为自己目录实际路径,编译得到ydb.so文件即可,然后在php.ini文件中加入如下配置,重启php进程就可以使用拉

       zend_extension=”ydb.so文件的路径 ”

       编译生成扩展so文件的具体过程见底下的评论回复,目前只支持linux环境下的使用,你也可以直接下载已经编译好的扩展文件:

       http://download.csdn.net/detail/micweaver/6823323  适用于php5.3以上版本
       http://download.csdn.net/detail/micweaver/6823361  适用于php5.2版本


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值