vantt/opentracing-jaeger-php

jaeger 的 PHP opentracing 客户端

v2.1.1 2021-02-19 08:05 UTC

This package is auto-updated.

Last update: 2024-09-19 16:10:48 UTC


README

Build Status Minimum PHP Version License Coverage Status

jaeger-php

安装

通过 composer 安装。

composer config minimum-stability dev
composer require vantt/opentracing-jaeger-php

初始化 Jaeger-php

$config = Config::getInstance();
$tracer = $config->initTracer('example', '0.0.0.0:6831');

128bit

$config->gen128bit();

从请求头中提取 span 上下文

$rootContext = $tracer->extract(Formats\TEXT_MAP, getallheaders());

将 span 上下文注入到请求头中

use OpenTracing\Formats;

$arrHeader = [];
$tracer->inject($span->getContext(), Formats\TEXT_MAP, $arrHeader);
$httpClient->request($url, $arrHeader);

用法

使用 SpanBuilder

此库扩展了原始 API,添加了一个新方法 buildSpan(operationName):SpanBuilderInterface。当使用此库时,你只需要关注 $tracer 实例上的 buildSpan(operationName)Tracer::buildSpan(operationName)

使用 SpanBuilder,我们可以利用编辑器的功能,通过以下 API 进行自动代码补全:

  • asChildOf($parentContext) 是一个 OpenTracing\SpanContextOpenTracing\Span 类型的对象。
  • withStartTimestamp(time()) 是一个表示任意精度的时间戳的浮点数、整数或 \DateTime
  • withTag(key,val) 是一个具有字符串键和标量值的数组,表示 OpenTracing 标签。
  • ignoreActiveSpan(bool)
  • finishSpanOnClose() 是一个布尔值,用于确定当作用域关闭时是否完成 span。
  • addReference()

以下是一些代码片段,用于演示一些重要的用例

$rootContext = $tracer->extract(Formats\TEXT_MAP, getallheaders());
$span = $tracer->buildSpan('my_span')
               ->asChildOf($rootContext)
               ->withTag('foo', 'bar')               
               ->withStartTimestamp(time())
               ->start();

$scope = $tracer->buildSpan('my_span')
                ->asChildOf($rootContext)
                ->withTag('foo', 'bar')               
                ->withStartTimestamp(time())
                ->startActive();

基于现有请求创建 Span

要启动一个新的 Span,可以使用 startSpan 方法。

use OpenTracing\Formats;
use OpenTracing\GlobalTracer;

...

// extract the span context
$spanContext = GlobalTracer::get()->extract(
    Formats\TEXT_MAP,
    getallheaders()
);

function doSomething() {
    ...

    // start a new span called 'my_span' and make it a child of the $spanContext
    $span = GlobalTracer::get()->buildSpan('my_operation_span_name')
                               ->start();
    ...
    
    // add some logs to the span
    $span->log([
        'event' => 'soft error',
        'type' => 'cache timeout',
        'waiter.millis' => 1500,
    ]);

    // finish the the span
    $span->finish();
}

通过创建 "root span" 来启动新的跟踪

始终可以创建一个没有父 span 或其他因果引用的 "root" Span

$span = $tracer->buildSpan('my_first_span')->start();
...
$span->finish();

活动 Span 和作用域管理器

对于大多数用例,建议使用 Tracer::startActiveSpan 函数来创建新的 spans。

以下是在 PHP 代码中使用的线性、两层深度的 span 树的示例

// At dispatcher level
$scope = $tracer->buildSpan('request')->start();
...
$scope->close();
// At controller level
$scope = $tracer->buildSpan('controller')->startActive();
...
$scope->close();
// At RPC calls level
$scope = $tracer->buildSpan('http')->startActive();
file_get_contents('https://php.ac.cn');
$scope->close();

当使用 Tracer::startActiveSpan 函数时,底层 tracer 使用一个称为作用域管理器的抽象来跟踪当前活动 span。

启动活动 span 将始终使用当前活动 span 作为父 span。如果没有父 span 可用,则新创建的 span 被认为是跟踪的 root span。

除非您使用同时跟踪多个 spans 的异步代码,例如在使用 cURL Multi Exec 或 MySQLi Polling 时,建议您在应用程序的每个地方都使用 Tracer::startActiveSpan

当前活动 span 在调用 $scope->close() 时会自动完成,如前例所示。

如果您不希望在调用 $scope->close() 时自动关闭 span,则必须在 startActiveSpan$options 参数中指定 'finish_span_on_close'=> false,

手动指定父 span 创建子 span

$tracer = GlobalTracer::get();
$parent = $tracer->startSpan('parent');

$child = $tracer->buildSpan('child_operation')
                ->asChildOf($parent)
                ->start();
...

$child->finish();

...

$parent->finish();

使用自动活动 span 管理创建子 span

每个新的 span 都会以活动 span 作为父 span,并占据其位置。

$parent = GlobalTracer::get()->buildSpan('parent')->startActive();

...

/*
 * Since the parent span has been created by using startActiveSpan we don't need
 * to pass a reference for this child span
 */
$child = GlobalTracer::get()->buildSpan('my_second_span')->startActive();

...

$child->close();

...

$parent->close();

序列化到线路上

use GuzzleHttp\Client;
use OpenTracing\Formats;

...

$tracer = GlobalTracer::get();

$spanContext = $tracer->extract(
    Formats\HTTP_HEADERS,
    getallheaders()
);

try {
    $span = $tracer->buildSpan('my_span')->asChildOf($spanContext)->start();

    $client = new Client;

    $headers = [];

    $tracer->inject(
        $span->getContext(),
        Formats\HTTP_HEADERS,
        $headers
    );

    $request = new \GuzzleHttp\Psr7\Request('GET', 'http://myservice', $headers);
    $client->send($request);
    ...

} catch (\Exception $e) {
    ...
}
...

从线路上反序列化

当使用 HTTP 头进行上下文传播时,您可以使用 Request$_SERVER 变量。

use OpenTracing\GlobalTracer;
use OpenTracing\Formats;

$tracer = GlobalTracer::get();
$spanContext = $tracer->extract(Formats\TEXT_MAP, getallheaders());
$tracer->buildSpan('my_span')->asChildOf($spanContext)->startActive();

启动 Span

$serverSpan = $tracer->startSpan('example HTTP', ['child_of' => $spanContext]);

分布式上下文传播

$serverSpan->addBaggageItem("version", "2.0.0");

注入到 Superglobals

$clientTrace->inject($clientSpan1->spanContext, Formats\TEXT_MAP, $_SERVER);

标签和日志

// tags are searchable in Jaeger UI
$span->setTag('http.status', '200');

// log record
$span->log(['error' => 'HTTP request timeout']);

关闭 Tracer

$config->setDisabled(true);

Zipkin B3 传播

不支持 分布式上下文传播

$config::$propagator = \Jaeger\Constants\PROPAGATOR_ZIPKIN;

完成 span 并刷新 Tracer

$span->finish();
$config->flush();

特性

  • 传输

    • 通过 UDP 使用 Thrift
  • 采样

    • ConstSampler
    • ProbabilisticSampler

参考

OpenTracing

Jaeger