class TraceContextPropagator
TraceContext is a propagator that supports the W3C Trace Context format (https://www.w3.org/TR/trace-context/)
This propagator will propagate the traceparent and tracestate headers to guarantee traces are not broken. It is up to the users of this propagator to choose if they want to participate in a trace by modifying the traceparent header and relevant parts of the tracestate header containing their proprietary information.
Hierarchy
- class \OpenTelemetry\API\Trace\Propagation\TraceContextPropagator implements \OpenTelemetry\Context\Propagation\TextMapPropagatorInterface
Expanded class hierarchy of TraceContextPropagator
File
-
vendor/
open-telemetry/ api/ Trace/ Propagation/ TraceContextPropagator.php, line 33
Namespace
OpenTelemetry\API\Trace\PropagationView source
final class TraceContextPropagator implements TextMapPropagatorInterface {
public const TRACEPARENT = 'traceparent';
public const TRACESTATE = 'tracestate';
private const VERSION = '00';
// Currently, only '00' is supported
public const FIELDS = [
self::TRACEPARENT,
self::TRACESTATE,
];
private static ?self $instance = null;
public static function getInstance() : self {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/** {@inheritdoc} */
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;
}
// Build and inject the traceparent header
$traceparent = self::VERSION . '-' . $spanContext->getTraceId() . '-' . $spanContext->getSpanId() . '-' . ($spanContext->isSampled() ? '01' : '00');
$setter->set($carrier, self::TRACEPARENT, $traceparent);
// Build and inject the tracestate header
// Spec says to avoid sending empty tracestate headers
if (($tracestate = (string) $spanContext->getTraceState()) !== '') {
$setter->set($carrier, self::TRACESTATE, $tracestate);
}
}
/** {@inheritdoc} */
public function extract($carrier, ?PropagationGetterInterface $getter = null, ?ContextInterface $context = null) : ContextInterface {
$getter ??= ArrayAccessGetterSetter::getInstance();
$context ??= Context::getCurrent();
$spanContext = self::extractImpl($carrier, $getter);
if (!$spanContext->isValid()) {
return $context;
}
return $context->withContextValue(Span::wrap($spanContext));
}
private static function extractImpl($carrier, PropagationGetterInterface $getter) : SpanContextInterface {
$traceparent = $getter->get($carrier, self::TRACEPARENT);
if ($traceparent === null) {
return SpanContext::getInvalid();
}
// traceParent = {version}-{trace-id}-{parent-id}-{trace-flags}
$pieces = explode('-', $traceparent);
// If the header does not have at least 4 pieces, it is invalid -- restart the trace.
if (count($pieces) < 4) {
return SpanContext::getInvalid();
}
[
$version,
$traceId,
$spanId,
$traceFlags,
] = $pieces;
/**
* Return invalid if:
* - Version is invalid (not 2 char hex or 'ff')
* - Trace version, trace ID, span ID or trace flag are invalid
*/
if (!TraceContextValidator::isValidTraceVersion($version) || !SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId) || !TraceContextValidator::isValidTraceFlag($traceFlags)) {
return SpanContext::getInvalid();
}
// Return invalid if the trace version is not a future version but still has > 4 pieces.
$versionIsFuture = hexdec($version) > hexdec(self::VERSION);
if (count($pieces) > 4 && !$versionIsFuture) {
return SpanContext::getInvalid();
}
// Only the sampled flag is extracted from the traceFlags (00000001)
$convertedTraceFlags = hexdec($traceFlags);
$isSampled = ($convertedTraceFlags & TraceFlags::SAMPLED) === TraceFlags::SAMPLED;
// Tracestate = 'Vendor1=Value1,...,VendorN=ValueN'
$rawTracestate = $getter->get($carrier, self::TRACESTATE);
if ($rawTracestate !== null) {
$tracestate = new TraceState($rawTracestate);
return SpanContext::createFromRemoteParent($traceId, $spanId, $isSampled ? TraceFlags::SAMPLED : TraceFlags::DEFAULT, $tracestate);
}
// Only traceparent header is extracted. No tracestate.
return SpanContext::createFromRemoteParent($traceId, $spanId, $isSampled ? TraceFlags::SAMPLED : TraceFlags::DEFAULT);
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title |
---|---|---|---|---|
TraceContextPropagator::$instance | private static | property | ||
TraceContextPropagator::extract | public | function | Extracts specific values from the provided carrier into the provided {via an { | Overrides TextMapPropagatorInterface::extract |
TraceContextPropagator::extractImpl | private static | function | ||
TraceContextPropagator::fields | public | function | Returns list of fields that will be used by this propagator. | Overrides TextMapPropagatorInterface::fields |
TraceContextPropagator::FIELDS | public | constant | ||
TraceContextPropagator::getInstance | public static | function | ||
TraceContextPropagator::inject | public | function | Injects specific values from the provided {via an { | Overrides TextMapPropagatorInterface::inject |
TraceContextPropagator::TRACEPARENT | public | constant | ||
TraceContextPropagator::TRACESTATE | public | constant | ||
TraceContextPropagator::VERSION | private | constant |