Add Jaeger Propagator (#1188)
* jaeger propagator * adjust readme * add baggage and debug flag * add units tests * code review fixs and baggage separator * update readme and register * improve more tests * fix php ci * fix knowvalues jaeger baggage
This commit is contained in:
parent
d3765662f9
commit
d8827f9681
|
|
@ -26,6 +26,8 @@ splits:
|
|||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/extension-propagator-b3.git"
|
||||
- prefix: "src/Extension/Propagator/CloudTrace"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/extension-propagator-cloudtrace.git"
|
||||
- prefix: "src/Extension/Propagator/Jaeger"
|
||||
target: "https://${GH_TOKEN}@github.com/opentelemetry-php/extension-propagator-jaeger.git"
|
||||
|
||||
# List of references to split (defined as regexp)
|
||||
origins:
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
"src/Contrib/Zipkin/_register.php",
|
||||
"src/Extension/Propagator/B3/_register.php",
|
||||
"src/Extension/Propagator/CloudTrace/_register.php",
|
||||
"src/Extension/Propagator/Jaeger/_register.php",
|
||||
"src/SDK/Logs/Exporter/_register.php",
|
||||
"src/SDK/Metrics/MetricExporter/_register.php",
|
||||
"src/SDK/Propagation/_register.php",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Extension\Propagator\Jaeger;
|
||||
|
||||
use OpenTelemetry\API\Baggage\Baggage;
|
||||
use OpenTelemetry\API\Baggage\Entry; /** @phan-suppress-current-line PhanUnreferencedUseNormal */
|
||||
use OpenTelemetry\Context\Context;
|
||||
use OpenTelemetry\Context\ContextInterface;
|
||||
use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter;
|
||||
use OpenTelemetry\Context\Propagation\PropagationGetterInterface;
|
||||
use OpenTelemetry\Context\Propagation\PropagationSetterInterface;
|
||||
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
|
||||
|
||||
/**
|
||||
* JaegerBaggagePropagator is a baggage propagator that supports the specification for the header
|
||||
* "uberctx" used for baggage propagation.
|
||||
* (https://www.jaegertracing.io/docs/1.52/client-libraries/#baggage)
|
||||
*/
|
||||
class JaegerBaggagePropagator implements TextMapPropagatorInterface
|
||||
{
|
||||
private const UBER_BAGGAGE_HEADER_PREFIX = 'uberctx-';
|
||||
|
||||
private static ?TextMapPropagatorInterface $instance = null;
|
||||
|
||||
public static function getInstance(): TextMapPropagatorInterface
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new JaegerBaggagePropagator();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function fields(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void
|
||||
{
|
||||
$setter ??= ArrayAccessGetterSetter::getInstance();
|
||||
$context ??= Context::getCurrent();
|
||||
|
||||
$baggage = Baggage::fromContext($context);
|
||||
|
||||
if ($baggage->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Entry $entry */
|
||||
foreach ($baggage->getAll() as $key => $entry) {
|
||||
$key = self::UBER_BAGGAGE_HEADER_PREFIX . $key;
|
||||
$value = rawurlencode((string) $entry->getValue());
|
||||
$setter->set($carrier, $key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
public function extract($carrier, PropagationGetterInterface $getter = null, ContextInterface $context = null): ContextInterface
|
||||
{
|
||||
$getter ??= ArrayAccessGetterSetter::getInstance();
|
||||
$context ??= Context::getCurrent();
|
||||
|
||||
$baggageKeys = $getter->keys($carrier);
|
||||
|
||||
if ($baggageKeys === []) {
|
||||
return $context;
|
||||
}
|
||||
|
||||
$baggageBuilder = Baggage::getBuilder();
|
||||
|
||||
foreach ($baggageKeys as $key) {
|
||||
if (strpos($key, self::UBER_BAGGAGE_HEADER_PREFIX) === 0) {
|
||||
$baggageKey = substr($key, strlen(self::UBER_BAGGAGE_HEADER_PREFIX));
|
||||
$value = $getter->get($carrier, $key) ?? '';
|
||||
$baggageBuilder->set($baggageKey, rawurldecode($value));
|
||||
}
|
||||
}
|
||||
|
||||
return $context->withContextValue($baggageBuilder->build());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Extension\Propagator\Jaeger;
|
||||
|
||||
use OpenTelemetry\Context\Context;
|
||||
use OpenTelemetry\Context\ContextKeyInterface;
|
||||
|
||||
/**
|
||||
* @psalm-internal \OpenTelemetry
|
||||
*/
|
||||
final class JaegerDebugFlagContextKey
|
||||
{
|
||||
private const KEY_NAME = 'jaeger-debug-key';
|
||||
|
||||
private static ?ContextKeyInterface $instance = null;
|
||||
|
||||
public static function instance(): ContextKeyInterface
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = Context::createKey(self::KEY_NAME);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Extension\Propagator\Jaeger;
|
||||
|
||||
use OpenTelemetry\API\Trace\Span;
|
||||
use OpenTelemetry\API\Trace\SpanContext;
|
||||
use OpenTelemetry\API\Trace\SpanContextInterface;
|
||||
use OpenTelemetry\API\Trace\SpanContextValidator;
|
||||
use OpenTelemetry\API\Trace\TraceFlags;
|
||||
use OpenTelemetry\Context\Context;
|
||||
use OpenTelemetry\Context\ContextInterface;
|
||||
use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter;
|
||||
use OpenTelemetry\Context\Propagation\PropagationGetterInterface;
|
||||
use OpenTelemetry\Context\Propagation\PropagationSetterInterface;
|
||||
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
|
||||
|
||||
/**
|
||||
* JaegerPropagator is a propagator that supports the specification for the header
|
||||
* "uber-trace-id" used for trace context propagation across service boundaries.
|
||||
* (https://www.jaegertracing.io/docs/1.52/client-libraries/#propagation-format)
|
||||
*/
|
||||
class JaegerPropagator implements TextMapPropagatorInterface
|
||||
{
|
||||
private const UBER_TRACE_ID_HEADER = 'uber-trace-id';
|
||||
|
||||
private const IS_NOT_SAMPLED = 0;
|
||||
private const IS_SAMPLED = 1;
|
||||
private const IS_DEBUG = 2;
|
||||
private const DEFAULT_PARENT_SPAN_ID = 0;
|
||||
|
||||
private const FIELDS = [
|
||||
self::UBER_TRACE_ID_HEADER,
|
||||
];
|
||||
|
||||
private static ?TextMapPropagatorInterface $instance = null;
|
||||
|
||||
public static function getInstance(): TextMapPropagatorInterface
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new JaegerPropagator();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function fields(): array
|
||||
{
|
||||
return self::FIELDS;
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
public function inject(&$carrier, PropagationSetterInterface $setter = null, ContextInterface $context = null): void
|
||||
{
|
||||
$setter ??= ArrayAccessGetterSetter::getInstance();
|
||||
$context ??= Context::getCurrent();
|
||||
$spanContext = Span::fromContext($context)->getContext();
|
||||
|
||||
if (!$spanContext->isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$flag = $this->getFlag($spanContext, $context);
|
||||
|
||||
$uberTraceId = sprintf(
|
||||
'%s:%s:%d:%d',
|
||||
$spanContext->getTraceId(),
|
||||
$spanContext->getSpanId(),
|
||||
self::DEFAULT_PARENT_SPAN_ID,
|
||||
$flag
|
||||
);
|
||||
|
||||
$setter->set($carrier, self::UBER_TRACE_ID_HEADER, $uberTraceId);
|
||||
}
|
||||
|
||||
/** {@inheritdoc} */
|
||||
public function extract($carrier, PropagationGetterInterface $getter = null, ContextInterface $context = null): ContextInterface
|
||||
{
|
||||
$getter ??= ArrayAccessGetterSetter::getInstance();
|
||||
$context ??= Context::getCurrent();
|
||||
|
||||
$spanContext = self::extractImpl($carrier, $getter, $context);
|
||||
if (!$spanContext->isValid()) {
|
||||
return $context;
|
||||
}
|
||||
|
||||
return $context->withContextValue(Span::wrap($spanContext));
|
||||
}
|
||||
|
||||
private function getFlag(SpanContextInterface $spanContext, ContextInterface $context): int
|
||||
{
|
||||
if ($spanContext->isSampled()) {
|
||||
if ($context->get(JaegerDebugFlagContextKey::instance())) {
|
||||
return self::IS_DEBUG | self::IS_SAMPLED;
|
||||
}
|
||||
|
||||
return self::IS_SAMPLED;
|
||||
}
|
||||
|
||||
return self::IS_NOT_SAMPLED;
|
||||
}
|
||||
|
||||
private static function extractImpl($carrier, PropagationGetterInterface $getter, ContextInterface &$context): SpanContextInterface
|
||||
{
|
||||
$headerValue = $getter->get($carrier, self::UBER_TRACE_ID_HEADER);
|
||||
|
||||
if ($headerValue === null) {
|
||||
return SpanContext::getInvalid();
|
||||
}
|
||||
|
||||
$pieces = explode(':', $headerValue);
|
||||
|
||||
if (count($pieces) != 4) {
|
||||
return SpanContext::getInvalid();
|
||||
}
|
||||
|
||||
[$traceId, $spanId, $parentSpanId, $traceFlags] = $pieces;
|
||||
|
||||
$traceId = str_pad($traceId, SpanContextValidator::TRACE_LENGTH, '0', STR_PAD_LEFT);
|
||||
$spanId = str_pad($spanId, SpanContextValidator::SPAN_LENGTH, '0', STR_PAD_LEFT);
|
||||
|
||||
if (!SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId)) {
|
||||
return SpanContext::getInvalid();
|
||||
}
|
||||
|
||||
if ((int) $traceFlags & self::IS_DEBUG) {
|
||||
$context = $context->with(JaegerDebugFlagContextKey::instance(), true);
|
||||
}
|
||||
|
||||
$isSampled = ((int) $traceFlags) & 1;
|
||||
|
||||
return SpanContext::createFromRemoteParent(
|
||||
$traceId,
|
||||
$spanId,
|
||||
$isSampled ? TraceFlags::SAMPLED : TraceFlags::DEFAULT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
[](https://github.com/opentelemetry-php/extension-propagator-jaeger/releases)
|
||||
[](https://github.com/open-telemetry/opentelemetry-php/tree/main/src/Extension/Propagator/Jaeger)
|
||||
[](https://github.com/opentelemetry-php/extension-propagator-jaeger)
|
||||
[](https://packagist.org/packages/open-telemetry/extension-propagator-jaeger/)
|
||||
[](https://packagist.org/packages/open-telemetry/extension-propagator-jaeger/)
|
||||
|
||||
# OpenTelemetry Extension
|
||||
### Jaeger Propagator
|
||||
|
||||
Jaeger is a propagator that supports the specification for the header "uber-trace-id" used for trace context propagation across
|
||||
service boundaries.(https://www.jaegertracing.io/docs/1.52/client-libraries/#propagation-format).
|
||||
OpenTelemetry PHP Jaeger Propagator Extension provides option to use Jaeger Baggage (https://www.jaegertracing.io/docs/1.52/client-libraries/#baggage) propagator.
|
||||
|
||||
### Usage
|
||||
For Jaeger trace propagator:
|
||||
```text
|
||||
JaegerPropagator::getInstance()
|
||||
```
|
||||
|
||||
For Jaeger baggage propagator:
|
||||
```text
|
||||
JaegerBaggagePropagator::getInstance()
|
||||
```
|
||||
|
||||
Both of the above have `extract` and `inject` methods available to extract and inject respectively into the
|
||||
header.
|
||||
|
||||
## Contributing
|
||||
|
||||
This repository is a read-only git subtree split.
|
||||
To contribute, please see the main [OpenTelemetry PHP monorepo](https://github.com/open-telemetry/opentelemetry-php).
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerBaggagePropagator;
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerPropagator;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
|
||||
use OpenTelemetry\SDK\Registry;
|
||||
|
||||
Registry::registerTextMapPropagator(
|
||||
KnownValues::VALUE_JAEGER,
|
||||
JaegerPropagator::getInstance()
|
||||
);
|
||||
|
||||
Registry::registerTextMapPropagator(
|
||||
KnownValues::VALUE_JAEGER_BAGGAGE,
|
||||
JaegerBaggagePropagator::getInstance()
|
||||
);
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "open-telemetry/extension-propagator-jaeger",
|
||||
"description": "Jaeger propagator extension for OpenTelemetry PHP.",
|
||||
"keywords": ["opentelemetry", "otel", "tracing", "apm", "extension", "propagator", "jaeger"],
|
||||
"type": "library",
|
||||
"support": {
|
||||
"issues": "https://github.com/open-telemetry/opentelemetry-php/issues",
|
||||
"source": "https://github.com/open-telemetry/opentelemetry-php",
|
||||
"docs": "https://opentelemetry.io/docs/php",
|
||||
"chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "opentelemetry-php contributors",
|
||||
"homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"open-telemetry/api": "^1.0",
|
||||
"open-telemetry/context": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"OpenTelemetry\\Extension\\Propagator\\Jaeger\\": "."
|
||||
},
|
||||
"files": [
|
||||
"_register.php"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,8 @@ interface KnownValues
|
|||
public const VALUE_B3_MULTI = 'b3multi';
|
||||
public const VALUE_CLOUD_TRACE = 'cloudtrace';
|
||||
public const VALUE_CLOUD_TRACE_ONEWAY = 'cloudtrace-oneway';
|
||||
public const VALUE_JAEGER = 'jaeger';
|
||||
public const VALUE_JAEGER_BAGGAGE = 'jaeger-baggage';
|
||||
public const VALUE_XRAY = 'xray';
|
||||
public const VALUE_OTTRACE = 'ottrace';
|
||||
public const VALUE_ALWAYS_ON = 'always_on';
|
||||
|
|
@ -109,6 +111,8 @@ interface KnownValues
|
|||
self::VALUE_B3_MULTI, // B3 Multi
|
||||
self::VALUE_CLOUD_TRACE, // GCP XCloudTraceContext
|
||||
self::VALUE_CLOUD_TRACE_ONEWAY, // GCP XCloudTraceContext OneWay (Extract)
|
||||
self::VALUE_JAEGER, // Jaeger Propagator
|
||||
self::VALUE_JAEGER_BAGGAGE, // Jaeger Baggage Propagator
|
||||
self::VALUE_XRAY, // AWS X-Ray (third party)
|
||||
self::VALUE_OTTRACE, // OT Trace (third party)
|
||||
self::VALUE_NONE, // No automatically configured propagator.
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ class ConsoleMetricExporter implements PushMetricExporterInterface, AggregationT
|
|||
'dropped_attributes_count' => $resource->getAttributes()->getDroppedAttributesCount(),
|
||||
];
|
||||
}
|
||||
|
||||
private function convertInstrumentationScope(InstrumentationScopeInterface $scope): array
|
||||
{
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ class B3SinglePropagatorTest extends TestCase
|
|||
$this->B3 => '-' . self::SPAN_ID_BASE16 . '-1',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_invalid_trace_id(): void
|
||||
{
|
||||
$this->assertInvalid([
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Extension\Propagator\Jaeger;
|
||||
|
||||
use OpenTelemetry\API\Baggage\Baggage;
|
||||
use OpenTelemetry\Context\Context;
|
||||
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerBaggagePropagator;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\Extension\Propagator\Jaeger\JaegerBaggagePropagator
|
||||
*/
|
||||
class JaegerBaggagePropagatorTest extends TestCase
|
||||
{
|
||||
private TextMapPropagatorInterface $propagator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->propagator = JaegerBaggagePropagator::getInstance();
|
||||
}
|
||||
|
||||
public function test_fields(): void
|
||||
{
|
||||
$this->assertSame(
|
||||
[],
|
||||
$this->propagator->fields()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_inject_empty_baggage(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject($carrier);
|
||||
|
||||
$this->assertEmpty($carrier);
|
||||
}
|
||||
|
||||
public function test_inject_baggage(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier,
|
||||
null,
|
||||
Context::getCurrent()->withContextValue(
|
||||
Baggage::getBuilder()
|
||||
->set('foo', 'bar')
|
||||
->build()
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
['uberctx-foo' => 'bar'],
|
||||
$carrier
|
||||
);
|
||||
}
|
||||
|
||||
public function test_inject_baggage_encoding(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier,
|
||||
null,
|
||||
Context::getCurrent()->withContextValue(
|
||||
Baggage::getBuilder()
|
||||
->set('foo', 'foo / bar')
|
||||
->build()
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
['uberctx-foo' => 'foo%20%2F%20bar'],
|
||||
$carrier
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_empty_baggage(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
Context::getCurrent(),
|
||||
$this->propagator->extract([])
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_baggage(): void
|
||||
{
|
||||
$carrier = [
|
||||
'uberctx-foo' => 'bar',
|
||||
'uberctxfoo' => 'bar',
|
||||
'another' => 'foo',
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertEquals(
|
||||
Baggage::getBuilder()->set('foo', 'bar')->build(),
|
||||
Baggage::fromContext($context)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\Extension\Propagator\Jaeger;
|
||||
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerDebugFlagContextKey;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\Extension\Propagator\Jaeger\JaegerDebugFlagContextKey
|
||||
*/
|
||||
class JaegerDebugFlagContextKeyTest extends TestCase
|
||||
{
|
||||
public function test_jaeger_debug_flag_key(): void
|
||||
{
|
||||
$this->assertSame(
|
||||
JaegerDebugFlagContextKey::instance(),
|
||||
JaegerDebugFlagContextKey::instance()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OpenTelemetry\Tests\Unit\Extension\Propagator\Jaeger;
|
||||
|
||||
use OpenTelemetry\API\Trace\SpanContext;
|
||||
use OpenTelemetry\API\Trace\SpanContextInterface;
|
||||
use OpenTelemetry\API\Trace\SpanContextValidator;
|
||||
use OpenTelemetry\API\Trace\TraceFlags;
|
||||
use OpenTelemetry\Context\Context;
|
||||
use OpenTelemetry\Context\ContextInterface;
|
||||
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerDebugFlagContextKey;
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerPropagator;
|
||||
use OpenTelemetry\SDK\Trace\Span;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \OpenTelemetry\Extension\Propagator\Jaeger\JaegerPropagator
|
||||
*/
|
||||
class JaegerPropagatorTest extends TestCase
|
||||
{
|
||||
private const TRACE_ID_BASE16 = '6bec5956ce56d66eb47802ab1cf6c4a0';
|
||||
private const SPAN_ID_BASE16 = '18dc27d6fabb2c47';
|
||||
private const TRACE_ID_SHORT = '53ce929d0e0e4736';
|
||||
private const SPAN_ID_SHORT = 'deadbef0';
|
||||
private const DEBUG_FLAG = '2';
|
||||
|
||||
private TextMapPropagatorInterface $propagator;
|
||||
private string $fields;
|
||||
|
||||
private function withSpanContext(SpanContextInterface $spanContext, ContextInterface $context): ContextInterface
|
||||
{
|
||||
return $context->withContextValue(Span::wrap($spanContext));
|
||||
}
|
||||
|
||||
private function generateTraceIdHeaderValue(
|
||||
string $traceId,
|
||||
string $spanId,
|
||||
string $flag
|
||||
): string {
|
||||
return sprintf(
|
||||
'%s:%s:0:%s',
|
||||
$traceId,
|
||||
$spanId,
|
||||
$flag
|
||||
);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->propagator = JaegerPropagator::getInstance();
|
||||
[$this->fields] = $this->propagator->fields();
|
||||
}
|
||||
|
||||
public function test_fields(): void
|
||||
{
|
||||
$this->assertSame(
|
||||
['uber-trace-id'],
|
||||
$this->propagator->fields()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_inject_invalid_context(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier,
|
||||
null,
|
||||
$this->withSpanContext(
|
||||
SpanContext::create(
|
||||
SpanContextValidator::INVALID_TRACE,
|
||||
SpanContextValidator::INVALID_SPAN,
|
||||
TraceFlags::SAMPLED
|
||||
),
|
||||
Context::getCurrent()
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEmpty($carrier);
|
||||
}
|
||||
|
||||
public function test_inject_sampled_context(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier,
|
||||
null,
|
||||
$this->withSpanContext(
|
||||
SpanContext::create(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
TraceFlags::SAMPLED
|
||||
),
|
||||
Context::getCurrent()
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
[$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
'1'
|
||||
)],
|
||||
$carrier
|
||||
);
|
||||
}
|
||||
|
||||
public function test_inject_not_sampled_context(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier,
|
||||
null,
|
||||
$this->withSpanContext(
|
||||
SpanContext::create(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
),
|
||||
Context::getCurrent()
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
[$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
'0'
|
||||
)],
|
||||
$carrier
|
||||
);
|
||||
}
|
||||
|
||||
public function test_inject_null_context(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier
|
||||
);
|
||||
|
||||
$this->assertEmpty($carrier);
|
||||
}
|
||||
|
||||
public function test_inject_sampled_with_debug_context(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier,
|
||||
null,
|
||||
$this->withSpanContext(
|
||||
SpanContext::create(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
TraceFlags::SAMPLED
|
||||
),
|
||||
Context::getCurrent()
|
||||
)->with(JaegerDebugFlagContextKey::instance(), self::DEBUG_FLAG)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
[$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
'3'
|
||||
)],
|
||||
$carrier
|
||||
);
|
||||
}
|
||||
|
||||
public function test_inject_not_sampled_with_debug_context(): void
|
||||
{
|
||||
$carrier = [];
|
||||
$this->propagator->inject(
|
||||
$carrier,
|
||||
null,
|
||||
$this->withSpanContext(
|
||||
SpanContext::create(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
),
|
||||
Context::getCurrent()
|
||||
)->with(JaegerDebugFlagContextKey::instance(), self::DEBUG_FLAG)
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
[$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
'0'
|
||||
)],
|
||||
$carrier
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_nothing(): void
|
||||
{
|
||||
$this->assertSame(
|
||||
Context::getCurrent(),
|
||||
$this->propagator->extract([])
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_sampled_context(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
'1'
|
||||
),
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertEquals(
|
||||
SpanContext::createFromRemoteParent(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
TraceFlags::SAMPLED
|
||||
),
|
||||
Span::fromContext($context)->getContext()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_not_sampled_context(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
'0'
|
||||
),
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertEquals(
|
||||
SpanContext::createFromRemoteParent(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16
|
||||
),
|
||||
Span::fromContext($context)->getContext()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_debug_context(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16,
|
||||
'2'
|
||||
),
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertEquals(
|
||||
SpanContext::createFromRemoteParent(
|
||||
self::TRACE_ID_BASE16,
|
||||
self::SPAN_ID_BASE16
|
||||
),
|
||||
Span::fromContext($context)->getContext()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_invalid_uber_trace_id(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => '000000000000000000000000deadbeef:00000000deadbef0:00',
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertSame(
|
||||
Context::getCurrent(),
|
||||
$context
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_invalid_trace_id(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => $this->generateTraceIdHeaderValue(
|
||||
SpanContextValidator::INVALID_TRACE,
|
||||
'00000000deadbef0',
|
||||
'1'
|
||||
),
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertSame(
|
||||
Context::getCurrent(),
|
||||
$context
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_invalid_span_id(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => $this->generateTraceIdHeaderValue(
|
||||
'000000000000000053ce929d0e0e4736',
|
||||
SpanContextValidator::INVALID_SPAN,
|
||||
'1'
|
||||
),
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertSame(
|
||||
Context::getCurrent(),
|
||||
$context
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_short_trace_id(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => $this->generateTraceIdHeaderValue(
|
||||
self::TRACE_ID_SHORT,
|
||||
'00000000deadbef0',
|
||||
'1'
|
||||
),
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertEquals(
|
||||
SpanContext::createFromRemoteParent(
|
||||
'000000000000000053ce929d0e0e4736',
|
||||
'00000000deadbef0',
|
||||
TraceFlags::SAMPLED
|
||||
),
|
||||
Span::fromContext($context)->getContext()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_extract_short_span_id(): void
|
||||
{
|
||||
$carrier = [
|
||||
$this->fields => $this->generateTraceIdHeaderValue(
|
||||
'000000000000000053ce929d0e0e4736',
|
||||
self::SPAN_ID_SHORT,
|
||||
'1'
|
||||
),
|
||||
];
|
||||
|
||||
$context = $this->propagator->extract($carrier);
|
||||
|
||||
$this->assertEquals(
|
||||
SpanContext::createFromRemoteParent(
|
||||
'000000000000000053ce929d0e0e4736',
|
||||
'00000000deadbef0',
|
||||
TraceFlags::SAMPLED
|
||||
),
|
||||
Span::fromContext($context)->getContext()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -106,9 +106,13 @@ class FactoryRegistryTest extends TestCase
|
|||
{
|
||||
return [
|
||||
['tracecontext'],
|
||||
['b3multi'],
|
||||
['baggage'],
|
||||
['b3'],
|
||||
['b3multi'],
|
||||
['cloudtrace'],
|
||||
['cloudtrace-oneway'],
|
||||
['jaeger'],
|
||||
['jaeger-baggage'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use OpenTelemetry\Context\Propagation\MultiTextMapPropagator;
|
|||
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator;
|
||||
use OpenTelemetry\Extension\Propagator\B3\B3Propagator;
|
||||
use OpenTelemetry\Extension\Propagator\CloudTrace\CloudTracePropagator;
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerBaggagePropagator;
|
||||
use OpenTelemetry\Extension\Propagator\Jaeger\JaegerPropagator;
|
||||
use OpenTelemetry\SDK\Common\Configuration\KnownValues;
|
||||
use OpenTelemetry\SDK\Common\Configuration\Variables;
|
||||
use OpenTelemetry\SDK\Propagation\PropagatorFactory;
|
||||
|
|
@ -54,6 +56,8 @@ class PropagatorFactoryTest extends TestCase
|
|||
[KnownValues::VALUE_B3, B3Propagator::class],
|
||||
[KnownValues::VALUE_CLOUD_TRACE, CloudTracePropagator::class],
|
||||
[KnownValues::VALUE_CLOUD_TRACE_ONEWAY, CloudTracePropagator::class],
|
||||
[KnownValues::VALUE_JAEGER, JaegerPropagator::class],
|
||||
[KnownValues::VALUE_JAEGER_BAGGAGE, JaegerBaggagePropagator::class],
|
||||
[KnownValues::VALUE_B3_MULTI, B3Propagator::class],
|
||||
[KnownValues::VALUE_NONE, NoopTextMapPropagator::class],
|
||||
[sprintf('%s,%s', KnownValues::VALUE_B3, KnownValues::VALUE_BAGGAGE), MultiTextMapPropagator::class],
|
||||
|
|
|
|||
Loading…
Reference in New Issue