Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. TraceContextPropagator.php

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\Propagation
View 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
RSS feed
Powered by Drupal