Published on

PHP中基于Jaeger的分布式链路追踪实践指南

Authors
  • avatar
    Name
    Liant
    Twitter
一、安装应用

主要是针对api接口调用链的监控

  • 安装三方包
composer require jonahgeorge/jaeger-client-php
  • 时序图
avator
  • 项目中使用
<?php

use Jaeger\Config;
use OpenTracing\GlobalTracer;
use OpenTracing\StartSpanOptions;

require __DIR__ . "/vendor/autoload.php";

/**
 * @throws Exception
 * 比如这里是一个公共的http请求方法
 */
function HttpRequest() {
    // 初始化全局配置可以放到框架启动的时候
    $config = new Config(
        [
            'sampler'       => [
                'type'  => Jaeger\SAMPLER_TYPE_CONST,
                'param' => true,
            ],
            'logging'       => true,
            // tags记录需要记录的参数有哪些
            "tags"          => [
                'http.url'         => 'http.url',
                'http.method'      => 'http.method',
                'http.status_code' => 'http.status_code',

                'db.query'      => 'db.query',
                'db.statement'  => 'db.statement',
                'db.query_time' => 'db.query_time',


                'path'   => 'request.path',
                'method' => 'request.method',
                'header' => 'request.header',

                'status_code' => 'response.status_code',
            ],
            // jaeger的测试环境地址
            "local_agent"   => [
                "reporting_host" => "web-jaeger.test.com",
                "reporting_port" => 5775
            ],
            'dispatch_mode' => Config::ZIPKIN_OVER_COMPACT_UDP,
        ],
        'project'
    );
    $config->initializeTracer();
    $tracer = GlobalTracer::get();
    // 模拟上一个请求的spanContext
    $lastSpanContext = $tracer->extract(TEXT_MAP, []);
    if ($lastSpanContext instanceof \Jaeger\SpanContext) {
        // 当前应用根span
        $rootSpan = $tracer->startSpan("request", [
            "references" => [
                new Reference(Reference::CHILD_OF, $lastSpanContext)
            ]
        ]);
    } else {
        // 当前应用根span
        $rootSpan = $tracer->startSpan("request");
    }
    $tracer->inject($rootSpan->getContext(),TEXT_MAP,$headers);

    $rootSpan->setTag("tag1", "ok");
    // 子span1
    $childSpan1 = $tracer->startSpan("db1", [
        "references" => [
            new Reference(Reference::CHILD_OF, $rootSpan->getContext())
        ]
    ]);
    $childSpan1->setTag("tag2", "ok");
    $childSpan1->finish();
    // 子span1的兄弟span2
    $brotherSpan1 = $tracer->startSpan("db2", [
        "references" => [
            new Reference(Reference::CHILD_OF, $rootSpan->getContext()),
            new Reference(Reference::FOLLOWS_FROM, $childSpan1->getContext()),
        ]
    ]);
    $brotherSpan1->setTag("tag3", "ok");
    $brotherSpan1->finish();

    $rootSpan->finish();
    $tracer->flush();
}
HttpRequest();

// 最终的jaeger日志就是这样的层级结构

/*
project request
    project db.query
        project redis.get
project db.insert
    project redis.hget
 */

trace
trace
trace