-
Notifications
You must be signed in to change notification settings - Fork 193
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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
- Loading branch information
1 parent
d376566
commit d8827f9
Showing
16 changed files
with
840 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
src/Extension/Propagator/Jaeger/JaegerBaggagePropagator.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
src/Extension/Propagator/Jaeger/JaegerDebugFlagContextKey.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
[![Releases](https://img.shields.io/badge/releases-purple)](https://github.com/opentelemetry-php/extension-propagator-jaeger/releases) | ||
[![Source](https://img.shields.io/badge/source-extension--propagator--jaeger-green)](https://github.com/open-telemetry/opentelemetry-php/tree/main/src/Extension/Propagator/Jaeger) | ||
[![Mirror](https://img.shields.io/badge/mirror-opentelemetry--php:extension--propagator--jaeger-blue)](https://github.com/opentelemetry-php/extension-propagator-jaeger) | ||
[![Latest Version](http://poser.pugx.org/open-telemetry/extension-propagator-jaeger/v/unstable)](https://packagist.org/packages/open-telemetry/extension-propagator-jaeger/) | ||
[![Stable](http://poser.pugx.org/open-telemetry/extension-propagator-jaeger/v/stable)](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). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.