前言
最近前端老是反馈API调用异常,说请求成功但是没有数据返回!
我写的代码怎么可能有bug,肯定是前端调用的方式不对!
经过一番套鼓,直接把请求参数和响应内容打印到控制台,果然不出我所料,请求缺少重要参数!
为了能让前端每次出问题后不用来找我(俗称甩锅),自己排查问题,我就想着把每次的请求参数和响应内容记录下来,前端查看请求记录详情排查问题。
刚好看到EasySwoole有这么一个组件(链路追踪)可以记录每次的请求信息,所以就写了这个甩锅工具。(说真的用起来真香)
话不多说先来一张甩锅工具效果图
每次请求需要记录的参数
请求地址、客户端IP、请求时间、请求状态、请求耗时、请求参数、响应内容
先创建mysql表CREATE TABLE `td_api_tracker_point_list` (
`pointd` varchar(18) NOT NULL,
`ip` varchar(100) DEFAULT '',
`create_date` varchar(30) DEFAULT '' COMMENT '访问时间 2020-02-23 12:00:00',
`pointName` varchar(100) DEFAULT NULL,
`parentId` varchar(18) DEFAULT NULL,
`depth` int(11) NOT NULL DEFAULT '0',
`isNext` int(11) NOT NULL DEFAULT '0',
`startTime` varchar(14) NOT NULL,
`endTime` varchar(14) DEFAULT NULL,
`spendTime` decimal(15,3) DEFAULT '0.000',
`status` varchar(10) NOT NULL,
`uri` varchar(255) DEFAULT '',
`result` text,
`data` text,
PRIMARY KEY (`pointd`),
UNIQUE KEY `trackerId_UNIQUE` (`pointd`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建ORM表模型
\App\Model\TrackerPoint\TrackerPointModel.php<?php
namespaceApp\Model\TrackerPoint;classTrackerPointModelextends\EasySwoole\ORM\AbstractModel
{protected$tableName='td_api_tracker_point_list';}
就是这么简单就创建好了表模型
安装链路追踪组件composer require easyswoole/tracker
使用链路追踪
在EasySwooleEvent.php的onRequest引入链路追踪并传入请求uri,get和post参数public static functiononRequest(Request$request,Response$response): bool
{$allow_origin=array("http://www.xxx1.com","https://www.xxxx2.com","http://127.0.0.1",);$origin=$request->getHeader('origin');if($origin!== []){$origin=$origin[0];if(in_array($origin,$allow_origin)){$response->withHeader('Access-Control-Allow-Origin',$origin);$response->withHeader('Access-Control-Allow-Methods','GET, POST, OPTIONS');$response->withHeader('Access-Control-Allow-Credentials','true');$response->withHeader('Access-Control-Allow-Headers','Content-Type, Authorization, X-Requested-With, token');if($request->getMethod() ==='OPTIONS') {$response->withStatus(Status::CODE_OK);return false;}
}
}/**
* 链路追踪
*/$point= PointContext::getInstance()->createStart($request->getUri()->__toString());$point->setStartArg(['uri'=>$request->getUri()->__toString(),'get'=>$request->getQueryParams(),'post'=>$request->getRequestParam()
]);return true;}
在EasySwooleEvent.php的afterRequest获取链路结果并写入到mysql表中//请求结束前执行public static functionafterRequest(Request$request,Response$response): void{// 真实IP$ip='';if(count($request->getHeader('x-real-ip'))) {$ip=$request->getHeader('x-real-ip')[0];}else{$params=$request->getServerParams();foreach(['http_client_ip','http_x_forward_for','x_real_ip','remote_addr']as$key) {if(isset($params[$key]) && !strcasecmp($params[$key],'unknown')) {$ip=$params[$key];break;}}}// 查看每次请求记录 http://host/index/tracker$point= PointContext::getInstance()->startPoint();$point->end();$array= Point::toArray($point);$rsp=$response->getBody();foreach($arrayas$k=>$v){$data['ip'] =$ip;$data['pointd'] =$v['pointId'];$data['pointName'] =$v['pointName'];$data['parentId'] =$v['parentId'];$data['depth'] =$v['depth'];$data['isNext'] =$v['isNext'];$data['startTime'] =$v['startTime'];$data['endTime'] =$v['endTime'];$data['spendTime'] =$v['endTime']-$v['startTime'];$data['status'] =$v['status'];$data['result'] = json_encode($v);$data['data'] =$rsp->__tostring();$data['uri'] =$v['startArg']['uri'];$data['create_date'] = date('Y-m-d H:i:s',time());if(strpos($v['startArg']['uri'],'index/tracker') !==false||strpos($v['startArg']['uri'],'index/tracker') !==false){//过滤index/tracker和index/getTracker这两个方法}else{\App\Model\TrackerPoint\TrackerPointModel::create()->data($data,false)->save();}}}
到这里基本大功告成了,剩下的就是写个页面把记录展示出来
安装模板视图composer require easyswoole/template
实现渲染引擎
创建文件\App\Template.php<?php
namespace App;
use EasySwoole\Template\RenderInterface;
class Template implements RenderInterface
{
protected $template;
function __construct()
{
$config = [
'view_path' => EASYSWOOLE_ROOT.'/App/Views/',
'cache_path' => EASYSWOOLE_ROOT.'/Temp/runtime/',
];
$this->template = new \think\Template($config);
}
public function render(string $template, array $data = [], array $options = []): ?string
{
// TODO: Implement render() method.
ob_start();
$this->template->assign($data);
$this->template->fetch($template);
$content = ob_get_contents() ;
return $content;
}
public function afterRender(?string $result, string $template, array $data = [], array $options = [])
{
// TODO: Implement afterRender() method.
}
public function onException(\Throwable $throwable): string
{
// TODO: Implement onException() method.
$msg = "{$throwable->getMessage()} at file:{$throwable->getFile()} line:{$throwable->getLine()}";
trigger_error($msg);
return $msg;
}
}
在EasySwooleEvent.php的mainServerCreate实例化视图并注入配置/*** **************** 实例化该Render,并注入你的驱动配置 *****************/Render::getInstance()->getConfig()->setRender(newTemplate());Render::getInstance()->attachServer(ServerManager::getInstance()->getSwooleServer());
在http控制器中使用视图模板渲染,存放模板的目录App/Views/index
控制器文件\App\HttpController\Index.php<?phpnamespaceApp \HttpController;useApp\Model\TrackerPoint\TrackerPointModel;useApp\Utility\MyQueue;useEasySwoole\Component\AtomicManager;useEasySwoole\Component\Timer;useEasySwoole\EasySwoole\Logger;useApp\Model\WechatModel;useEasySwoole\Http\AbstractInterface\Controller;useEasySwoole\ORM\DbManager;useEasySwoole\Queue\Job;useEasySwoole\Template\Render;useEasySwoole\Tracker\PointContext;useElasticsearch\ClientBuilder;use\Swoole\Coroutineasco;useEasySwoole\Mysqli\QueryBuilder;useEasySwoole\Jwt\Jwt;use\PhpOffice\PhpSpreadsheet\Spreadsheet;use\PhpOffice\PhpSpreadsheet\Writer\Xlsx;classIndexextendsController{protected functiononRequest(?string$action): ?bool{return true;}//渲染模板public functiontracker(){$this->response()->write(Render::getInstance()->render('index/tracker',['row'=> time(),'json'=>json_encode([])]));}//获取链路记录列表public functiongetTracker(){$model= TrackerPointModel::create();$param=$this->request()->getRequestParam();if(!empty($param['uri']) ){$model->where('uri',"%{$param['uri']}%",'like');}$limit=$param['limit']??10;$p=$param['page']??1;$data['code'] =0;$data['msg'] ='';$list=$model->withTotalCount()->limit($p* ($p-1),$limit)->order('pointd','desc')->select();$data['count'] =$model->lastQueryResult()->getTotalCount();foreach($listas$k=>$v){$uri= explode(':9501/',$v['uri']);if(count($uri)!=2){$uri= explode(':80/',$v['uri']);}$list[$k]['uri'] = !empty($uri[1])?$uri[1]:$v['uri'];$result= json_decode($v['result'],true);unset($result['startArg']['uri']);$list[$k]['result'] = json_encode($result['startArg']);if(strpos($v['uri'],'tracker') !==false||strpos($v['uri'],'getTracker') !==false){$list[$k]['data'] ='';}}$data['data'] =$list;$data['sql'] =$model->lastQuery()->getLastPrepareQuery();$this->response()->write(json_encode($data));return false;}
//测试计数器functionindex(){$this->response()->withHeader('Content-type','text/html;charset=utf-8');$atomic= AtomicManager::getInstance()->get('second');$atomic->add(1);echodate('i:s',time()).'计数器:'.$atomic->get().PHP_EOL;$this->response()->write('计数器:'.$atomic->get().PHP_EOL);}}
甩锅完毕
最后甩锅工具完成,直接丢链接给前端 http://你的域名:9501/index/tracker
本文为够意思原创文章,转载无需和我联系,但请注明来自够意思博客blog.go1s.cn:够意思博客 » EasySwoole利用链路追踪组件制作甩锅工具