开源项目:Ivory-jaeger-php-client :安装文档

@李彪  October 29, 2018

一. 背景描述

Ivory-jaeger-php-client是一款全链路跟踪客户端工具,基于PHP开发,项目发源自Jaeger-PHP,框架建立在OpenTracing 1.0.0-beta2 ,这篇文章主要讲解工具的安装过程。

二. 插件依赖关系

插件主体为 Ivory-jaeger-php-client 代码包,这个代码包依赖两个包:

  1. opentracing/opentracing ( 1.0.0-beta2)
  2. packaged/thrift ( 0.10.0)

三. 安装步骤

3.1 Ivory-jaeger-php-client 代码包配置

  • 复制 Ivory-jaeger-php-client 代码包到vendor目录下,相关目录如下
  • 修改composer.json文件中的autoload-psr-4选项
    "autoload": {
        "psr-4": {
            "Jaeger\\": "./vendor/ivory-jaeger-php-client/src/Jaeger"
        },
        "files": [
            "./vendor/ivory-jaeger-php-client/src/Jaeger/Constants.php"
        ]
    },
  • 生成自动加载索引
    在根composer.json目录中执行以下命令构建自动加载索引。
composer dump-autoload
  • 引入opentracing 和 thrift代码包
composer require opentracing/opentracing:1.0.0-beta2

composer require packaged/thrift:0.10.0

四. 安装测试

这里提供一个安装后的使用样例,对guzzlehttp包的request函数进行修改,添加对于http请求的全链路跟踪功能。

use Jaeger\Config as JaegerConfig;
use OpenTracing\Formats;
use OpenTracing\Reference;
use Order\Base\Exception;

private $baseUriString;  //修改1:添加此变量用于记录baseuri,因为guzzle构造url分baseuri和uri区别

public function __construct(array $config = [])
{
        $this->baseUriString =''; //修改2:初始化变量
        if (!isset($config['handler'])) {
            $config['handler'] = HandlerStack::create();
        } elseif (!is_callable($config['handler'])) {
            throw new \InvalidArgumentException('handler must be a callable');
        }

        // Convert the base_uri to a UriInterface
        if (isset($config['base_uri'])) {
            $this->baseUriString = $config['base_uri']; //修改3:把base_uri中的值进行存储
            $config['base_uri'] = Psr7\uri_for($config['base_uri']);
        }

        $this->configureDefaults($config);
}

//关于request函数的修改只是构造一个tracer和span,但是框架主tracer和主span需要在kernel层做修改。
public function request($method, $uri = '', array $options = [])
{
        try{
            $JaegerConfig = JaegerConfig::getInstance(); //修改4:创建jaeger实例
            $clientTrace = $JaegerConfig->initTrace('Guzzle HTTP'); //修改4:初始化tracer
            $injectTarget = []; //修改4:初始化注射变量
            $spanContext = $clientTrace->extract(Formats\TEXT_MAP, $_SERVER); //修改4:从$_SERVER变量解析tracer信息
            $fullUriString = $this->baseUriString.$uri; //修改4:构造完整url路径当作span name
            $clientSpan = $clientTrace->startSpan($fullUriString,
                ['references' => [
                    //    Reference::create(Reference::FOLLOWS_FROM, $clientSapn1->spanContext),
                    Reference::create(Reference::CHILD_OF, $spanContext)
                ]]);

            $clientTrace->inject($clientSpan->spanContext, Formats\TEXT_MAP, $injectTarget);  //修改4:注射当前client的span内容

            foreach ($injectTarget as $key => $val){
                $options['headers'][$key] = $val ;  //修改4:把注射内容存储进request的header参数中,向下一级别链路传播。
            }

            $options[RequestOptions::SYNCHRONOUS] = true;
            $res = $this->requestAsync($method, $uri, $options)->wait();

            $clientSpan->setTags(['http.status_code' => $res->getStatusCode()
                , 'http.method' => $method, 'http.url' => $fullUriString]); //修改4:设置span的相关tag参数
            $clientSpan->finish(); //修改4:当前clientspan终止
            return $res;

        }catch (\Exception $ex){
            $clientSpan->setTags(['http.status_code' => $ex->getCode()
                , 'http.method' => $method, 'http.url' => $fullUriString,'error'=>true]);//修改4:request发生异常,把相关错误状态存入相关span
            $clientSpan->log(['exception' => $ex->getMessage()]);//修改4:request发生异常,存入一个异常日志

            $backtrace = debug_backtrace(); //修改4:request发生异常,存入异常调用来源
            array_shift($backtrace);
            $clientSpan->log(['exception_from' => $backtrace[0]['class'].'->'.$backtrace[0]['function']]);
            $clientSpan->log(['request_options' => json_encode($options)]);
            $clientSpan->finish();
            throw $ex;
        }
}

评论已关闭