够意思博客够意思博客够意思博客

EasySwoole利用链路追踪组件制作甩锅工具

前言

最近前端老是反馈API调用异常,说请求成功但是没有数据返回!

我写的代码怎么可能有bug,肯定是前端调用的方式不对!

经过一番套鼓,直接把请求参数和响应内容打印到控制台,果然不出我所料,请求缺少重要参数!

为了能让前端每次出问题后不用来找我(俗称甩锅),自己排查问题,我就想着把每次的请求参数和响应内容记录下来,前端查看请求记录详情排查问题。

刚好看到EasySwoole有这么一个组件(链路追踪)可以记录每次的请求信息,所以就写了这个甩锅工具。(说真的用起来真香)

话不多说先来一张甩锅工具效果图

EasySwoole利用链路追踪组件制作甩锅工具(图1)

每次请求需要记录的参数

    请求地址、客户端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

namespace
App\Model\TrackerPoint;

class TrackerPointModel extends \EasySwoole\ORM\AbstractModel
{
 
protected $tableName = 'td_api_tracker_point_list';
}

就是这么简单就创建好了表模型

安装链路追踪组件

composer require easyswoole/tracker

组件地址及使用方法:https://www.easyswoole.com/Cn/Components/tracker.html#Tracker

使用链路追踪

在EasySwooleEvent.php的onRequest引入链路追踪并传入请求uri,get和post参数

  public static function onRequest(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 function afterRequest(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 ($array as $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(new Template());
Render::getInstance()->attachServer(ServerManager::getInstance()->getSwooleServer());

在http控制器中使用视图模板渲染,存放模板的目录App/Views/index

控制器文件\App\HttpController\Index.php

<?php
namespace App\HttpController;

use App\Model\TrackerPoint\TrackerPointModel;
use App\Utility\MyQueue;
use EasySwoole\Component\AtomicManager;
use EasySwoole\Component\Timer;
use EasySwoole\EasySwoole\Logger;
use App\Model\WechatModel;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\ORM\DbManager;
use EasySwoole\Queue\Job;
use EasySwoole\Template\Render;
use EasySwoole\Tracker\PointContext;
use Elasticsearch\ClientBuilder;
use \Swoole\Coroutine as co;
use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\Jwt\Jwt;
use \PhpOffice\PhpSpreadsheet\Spreadsheet;
use \PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class Index extends Controller
{
   protected function onRequest(?string $action): ?bool
   {
       return true;
   }
   //渲染模板
   public function tracker(){
       $this->response()->write(Render::getInstance()->render('index/tracker',['row'=> time(),'json'=>json_encode([])]));
   }
   //获取链路记录列表
   public function getTracker(){
       $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 ($list as $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;
   }

     //测试计数器
   function index(){
       $this->response()->withHeader('Content-type','text/html;charset=utf-8');

       $atomic = AtomicManager::getInstance()->get('second');
       $atomic->add(1);
       echo date('i:s',time()).'计数器:'.$atomic->get().PHP_EOL;
       $this->response()->write('计数器:'.$atomic->get().PHP_EOL);

   }
 
}

甩锅完毕

最后甩锅工具完成,直接丢链接给前端  http://你的域名:9501/index/tracker

EasySwoole利用链路追踪组件制作甩锅工具(图2)



本文为够意思原创文章,转载无需和我联系,但请注明来自够意思博客blog.go1s.cn:够意思博客 » EasySwoole利用链路追踪组件制作甩锅工具

加载中~