Skip to content

Commit

Permalink
Propagate W3C spec level 2 random-trace-id flag
Browse files Browse the repository at this point in the history
  • Loading branch information
Nevay committed Apr 1, 2024
1 parent 7ec0e90 commit fdc1c6a
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 20 deletions.
36 changes: 16 additions & 20 deletions src/API/Trace/Propagation/TraceContextPropagator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
use OpenTelemetry\API\Trace\SpanContext;
use OpenTelemetry\API\Trace\SpanContextInterface;
use OpenTelemetry\API\Trace\SpanContextValidator;
use OpenTelemetry\API\Trace\TraceFlags;
use OpenTelemetry\API\Trace\TraceState;
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;
use function sprintf;

/**
* TraceContext is a propagator that supports the W3C Trace Context format
Expand All @@ -34,7 +34,8 @@ final class TraceContextPropagator implements TextMapPropagatorInterface
{
public const TRACEPARENT = 'traceparent';
public const TRACESTATE = 'tracestate';
private const VERSION = '00'; // Currently, only '00' is supported
private const VERSION = 0x00; // Currently, only '00' is supported
private const SUPPORTED_FLAGS = 0x03;

public const FIELDS = [
self::TRACEPARENT,
Expand Down Expand Up @@ -70,7 +71,13 @@ public function inject(&$carrier, PropagationSetterInterface $setter = null, Con
}

// Build and inject the traceparent header
$traceparent = self::VERSION . '-' . $spanContext->getTraceId() . '-' . $spanContext->getSpanId() . '-' . ($spanContext->isSampled() ? '01' : '00');
$traceparent = sprintf(
'%02x-%s-%s-%02x',
self::VERSION,
$spanContext->getTraceId(),
$spanContext->getSpanId(),
$spanContext->getTraceFlags() & self::SUPPORTED_FLAGS,
);
$setter->set($carrier, self::TRACEPARENT, $traceparent);

// Build and inject the tracestate header
Expand Down Expand Up @@ -102,7 +109,7 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter
}

// traceParent = {version}-{trace-id}-{parent-id}-{trace-flags}
$pieces = explode('-', $traceparent);
$pieces = explode('-', $traceparent, 5);

// If the header does not have at least 4 pieces, it is invalid -- restart the trace.
if (count($pieces) < 4) {
Expand All @@ -125,33 +132,22 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter
}

// Return invalid if the trace version is not a future version but still has > 4 pieces.
$versionIsFuture = hexdec($version) > hexdec(self::VERSION);
$versionIsFuture = hexdec($version) > 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;
$traceFlags = hexdec($traceFlags) & self::SUPPORTED_FLAGS;

// 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
);
}
$tracestate = $rawTracestate !== null ? new TraceState($rawTracestate) : null;

// Only traceparent header is extracted. No tracestate.
return SpanContext::createFromRemoteParent(
$traceId,
$spanId,
$isSampled ? TraceFlags::SAMPLED : TraceFlags::DEFAULT
$traceFlags,
$tracestate,
);
}
}
23 changes: 23 additions & 0 deletions tests/Unit/API/Trace/Propagation/TraceContextPropagatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,29 @@ public function test_extract_non_sampled_context_with_trace_state(): void
);
}

public function test_extract_random_flag(): void
{
$carrier = [
TraceContextPropagator::TRACEPARENT => '00-12345678901234567890123456789012-1234567890123456-02',
];

$spanContext = $this->getSpanContext($this->traceContextPropagator->extract($carrier));
$this->assertSame('12345678901234567890123456789012', $spanContext->getTraceId());
$this->assertSame('1234567890123456', $spanContext->getSpanId());
$this->assertSame(0x2, $spanContext->getTraceFlags() & 0x2);
}

public function test_inject_random_flag(): void
{
$context = $this->withSpanContext(SpanContext::create('12345678901234567890123456789012', '1234567890123456', 0x2), Context::getCurrent());

$carrier = [];
$this->traceContextPropagator->inject($carrier, context: $context);

$this->assertArrayHasKey(TraceContextPropagator::TRACEPARENT, $carrier);
$this->assertSame('00-12345678901234567890123456789012-1234567890123456-02', $carrier[TraceContextPropagator::TRACEPARENT]);
}

public function test_extract_and_inject(): void
{
$traceParent = '00-' . self::TRACE_ID_BASE16 . '-' . self::SPAN_ID_BASE16 . '-01';
Expand Down

0 comments on commit fdc1c6a

Please sign in to comment.