Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor span context #801

Merged
merged 46 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c3066fa
Otel-php:632 Move stack trace formatting out of Span class
amber0612 Jun 1, 2022
99a4273
added function usages
amber0612 Jun 1, 2022
c8365d1
fix linting errors
amber0612 Jun 2, 2022
f10cf31
Merging to upgrade to upstream
amber0612 Jun 21, 2022
f584a05
Merge remote-tracking branch 'upstream/main'
amber0612 Jun 25, 2022
b02b7ea
Added documentation for adding Span Attributes
amber0612 Jun 25, 2022
296a486
removing TracingUtl class
amber0612 Jun 25, 2022
90865ed
Refactor TraceState's __toString method
amber0612 Jun 27, 2022
1ba59c9
Added path with @covers to remove warnings
amber0612 Jul 5, 2022
e3c5fc8
Merge branch 'open-telemetry:main' into main
amber0612 Jul 6, 2022
947b2de
Added @coversDefaultClass annotation
amber0612 Jul 13, 2022
f2de6d2
Merge branch 'open-telemetry:main' into main
amber0612 Jul 19, 2022
cd3e135
fix to check if iterable is empty
amber0612 Jul 20, 2022
d0b2dc5
fixed for faling test case
amber0612 Jul 20, 2022
31882dc
unit test
amber0612 Jul 25, 2022
0c30963
Merge remote-tracking branch 'upstream/main'
amber0612 Jul 25, 2022
6fd76f1
Resolved review Comments
amber0612 Jul 25, 2022
cb9f1e6
reverting changes
amber0612 Jul 27, 2022
22be517
removing check for empty iterable span list
amber0612 Jul 27, 2022
432d4d9
review changes for SpanProcessor incorrect calls to SpanExporter::for…
amber0612 Aug 1, 2022
70bdd97
updated test case
amber0612 Aug 1, 2022
43d357c
Merge remote-tracking branch 'upstream/main'
amber0612 Aug 2, 2022
7e451ed
resolved review comments
amber0612 Aug 2, 2022
a0d58ac
reverted changes for batch span processors
amber0612 Aug 16, 2022
2aed437
reverting changes for batch span proccessor
amber0612 Aug 16, 2022
19c753f
Merge remote-tracking branch 'upstream/main'
amber0612 Aug 16, 2022
4fbb7cf
merge upstream and changes
amber0612 Aug 16, 2022
fcc9e73
updating changes
amber0612 Aug 16, 2022
d8c935a
Refactoring SpanContext
amber0612 Aug 18, 2022
f2dd0c2
sync with upstream
amber0612 Aug 24, 2022
bcbabec
sync with main
amber0612 Aug 24, 2022
809b55c
updating changes
amber0612 Aug 24, 2022
112db59
updated test cases
amber0612 Aug 25, 2022
941f368
updated changes suggested after review
amber0612 Aug 26, 2022
c9de089
Revert "Reverting back to previous commit"
amber0612 Sep 2, 2022
b09785d
updating changes after review
amber0612 Sep 2, 2022
c67c4b7
unused use statement
amber0612 Sep 2, 2022
a2a7752
added unit test and resolved review comments
amber0612 Sep 7, 2022
37f98a8
Removed Double underscores from constant variables
amber0612 Sep 8, 2022
f370c7c
Removed constants from SpanContext.php to remove duplicacy
amber0612 Sep 8, 2022
9a782f8
updated failing test
amber0612 Sep 8, 2022
4f030eb
Moving Factory Methods back into SpanContext.php
amber0612 Sep 21, 2022
facc7e5
modified constructor of SpanContext
amber0612 Sep 21, 2022
bd8dcd9
updated SpanContext
amber0612 Sep 21, 2022
1ca90a8
Modified use of additional if statement
amber0612 Sep 21, 2022
3cf9c1c
corrected parsing error
amber0612 Sep 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/API/Trace/Propagation/TraceContextPropagator.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use OpenTelemetry\API\Trace\AbstractSpan;
use OpenTelemetry\API\Trace\SpanContext;
use OpenTelemetry\API\Trace\SpanContextInterface;
use OpenTelemetry\API\Trace\SpanContextValidator;
use OpenTelemetry\API\Trace\TraceState;
use OpenTelemetry\Context\Context;
use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter;
Expand Down Expand Up @@ -113,10 +114,10 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter
* - Version is invalid (not 2 char hex or 'ff')
* - Trace version, trace ID, span ID or trace flag are invalid
*/
if (!SpanContext::isValidTraceVersion($version)
|| !SpanContext::isValidTraceId($traceId)
|| !SpanContext::isValidSpanId($spanId)
|| !SpanContext::isValidTraceFlag($traceFlags)
if (!TraceContextValidator::isValidTraceVersion($version)
|| !SpanContextValidator::isValidTraceId($traceId)
|| !SpanContextValidator::isValidSpanId($spanId)
|| !TraceContextValidator::isValidTraceFlag($traceFlags)
) {
return SpanContext::getInvalid();
}
Expand All @@ -129,7 +130,7 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter

// Only the sampled flag is extracted from the traceFlags (00000001)
$convertedTraceFlags = hexdec($traceFlags);
$isSampled = ($convertedTraceFlags & SpanContext::SAMPLED_FLAG) === SpanContext::SAMPLED_FLAG;
$isSampled = ($convertedTraceFlags & SpanContextInterface::TRACE_FLAG_SAMPLED) === SpanContextInterface::TRACE_FLAG_SAMPLED;

// Tracestate = 'Vendor1=Value1,...,VendorN=ValueN'
$rawTracestate = $getter->get($carrier, self::TRACESTATE);
Expand Down
31 changes: 31 additions & 0 deletions src/API/Trace/Propagation/TraceContextValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\API\Trace\Propagation;

use function strlen;

class TraceContextValidator
{
public const TRACE_FLAG_LENGTH = 2;
public const TRACE_VERSION_REGEX = '/^(?!ff)[\da-f]{2}$/';

/**
* @param string $traceVersion
* @return bool Returns a value that indicates whether a trace version is valid.
*/
public static function isValidTraceVersion(string $traceVersion): bool
{
return 1 === preg_match(self::TRACE_VERSION_REGEX, $traceVersion);
}

/**
* @return bool Returns a value that indicates whether trace flag is valid
* TraceFlags must be exactly 1 bytes (1 char) representing a bit field
*/
public static function isValidTraceFlag($traceFlag): bool
{
return ctype_xdigit($traceFlag) && strlen($traceFlag) === self::TRACE_FLAG_LENGTH;
}
}
139 changes: 45 additions & 94 deletions src/API/Trace/SpanContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,92 +4,9 @@

namespace OpenTelemetry\API\Trace;

use OpenTelemetry\API\Trace as API;
use function strlen;
use function strtolower;

final class SpanContext implements API\SpanContextInterface
final class SpanContext implements SpanContextInterface
{
public const INVALID_TRACE = '00000000000000000000000000000000';
public const TRACE_VERSION_REGEX = '/^(?!ff)[\da-f]{2}$/';
public const VALID_TRACE = '/^[0-9a-f]{32}$/';
public const TRACE_LENGTH = 32;
public const INVALID_SPAN = '0000000000000000';
public const VALID_SPAN = '/^[0-9a-f]{16}$/';
public const SPAN_LENGTH = 16;
public const SPAN_LENGTH_BYTES = 8;
public const SAMPLED_FLAG = 1;
public const TRACE_FLAG_LENGTH = 2;

private static ?API\SpanContextInterface $invalidContext = null;

/** @inheritDoc */
public static function createFromRemoteParent(string $traceId, string $spanId, int $traceFlags = self::TRACE_FLAG_DEFAULT, ?API\TraceStateInterface $traceState = null): API\SpanContextInterface
{
return new self(
$traceId,
$spanId,
$traceFlags,
true,
$traceState,
);
}

/** @inheritDoc */
public static function create(string $traceId, string $spanId, int $traceFlags = self::TRACE_FLAG_DEFAULT, ?API\TraceStateInterface $traceState = null): API\SpanContextInterface
{
return new self(
$traceId,
$spanId,
$traceFlags,
false,
$traceState,
);
}

/** @inheritDoc */
public static function getInvalid(): API\SpanContextInterface
{
if (null === self::$invalidContext) {
self::$invalidContext = self::create(self::INVALID_TRACE, self::INVALID_SPAN, 0);
}

return self::$invalidContext;
}

/**
* @param string $traceVersion
* @return bool Returns a value that indicates whether a trace version is valid.
*/
public static function isValidTraceVersion(string $traceVersion): bool
{
return 1 === preg_match(self::TRACE_VERSION_REGEX, $traceVersion);
}

/**
* @return bool Returns a value that indicates whether a trace id is valid
*/
public static function isValidTraceId($traceId): bool
{
return ctype_xdigit($traceId) && strlen($traceId) === self::TRACE_LENGTH && $traceId !== self::INVALID_TRACE && $traceId === strtolower($traceId);
}

/**
* @return bool Returns a value that indicates whether a span id is valid
*/
public static function isValidSpanId($spanId): bool
{
return ctype_xdigit($spanId) && strlen($spanId) === self::SPAN_LENGTH && $spanId !== self::INVALID_SPAN && $spanId === strtolower($spanId);
}

/**
* @return bool Returns a value that indicates whether trace flag is valid
* TraceFlags must be exactly 1 bytes (1 char) representing a bit field
*/
public static function isValidTraceFlag($traceFlag): bool
{
return ctype_xdigit($traceFlag) && strlen($traceFlag) === self::TRACE_FLAG_LENGTH;
}
private static ?SpanContextInterface $invalidContext = null;

/**
* @see https://www.w3.org/TR/trace-context/#trace-flags
Expand All @@ -99,8 +16,8 @@ public static function isValidTraceFlag($traceFlag): bool

private string $traceId;
private string $spanId;
private ?API\TraceStateInterface $traceState;
private bool $isValid;
private ?TraceStateInterface $traceState;
private bool $isValid = true;
private bool $isRemote;
private int $traceFlags;

Expand All @@ -109,22 +26,22 @@ private function __construct(
string $spanId,
int $traceFlags,
bool $isRemote,
API\TraceStateInterface $traceState = null
TraceStateInterface $traceState = null
) {
// TraceId must be exactly 16 bytes (32 chars) and at least one non-zero byte
// SpanId must be exactly 8 bytes (16 chars) and at least one non-zero byte
if (!self::isValidTraceId($traceId) || !self::isValidSpanId($spanId)) {
$traceId = self::INVALID_TRACE;
$spanId = self::INVALID_SPAN;
if (!SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId)) {
$traceId = SpanContextValidator::INVALID_TRACE;
$spanId = SpanContextValidator::INVALID_SPAN;
$this->isValid=false;
}

$this->traceId = $traceId;
$this->spanId = $spanId;
$this->traceState = $traceState;
$this->isRemote = $isRemote;
$this->isSampled = ($traceFlags & self::SAMPLED_FLAG) === self::SAMPLED_FLAG;
$this->isSampled = ($traceFlags & self::TRACE_FLAG_SAMPLED) === self::TRACE_FLAG_SAMPLED;
$this->traceFlags = $traceFlags;
$this->isValid = self::isValidTraceId($this->traceId) && self::isValidSpanId($this->spanId);
}

public function getTraceId(): string
Expand All @@ -137,7 +54,7 @@ public function getSpanId(): string
return $this->spanId;
}

public function getTraceState(): ?API\TraceStateInterface
public function getTraceState(): ?TraceStateInterface
{
return $this->traceState;
}
Expand All @@ -161,4 +78,38 @@ public function getTraceFlags(): int
{
return $this->traceFlags;
}

/** @inheritDoc */
public static function createFromRemoteParent(string $traceId, string $spanId, int $traceFlags = self::TRACE_FLAG_DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface
{
return new self(
$traceId,
$spanId,
$traceFlags,
true,
$traceState,
);
}

/** @inheritDoc */
public static function create(string $traceId, string $spanId, int $traceFlags = self::TRACE_FLAG_DEFAULT, ?TraceStateInterface $traceState = null): SpanContextInterface
{
return new self(
$traceId,
$spanId,
$traceFlags,
false,
$traceState,
);
}

/** @inheritDoc */
public static function getInvalid(): SpanContextInterface
{
if (null === self::$invalidContext) {
self::$invalidContext = self::create(SpanContextValidator::INVALID_TRACE, SpanContextValidator::INVALID_SPAN, 0);
}

return self::$invalidContext;
}
}
35 changes: 35 additions & 0 deletions src/API/Trace/SpanContextValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace OpenTelemetry\API\Trace;

use function strlen;
use function strtolower;

class SpanContextValidator
{
public const VALID_SPAN = '/^[0-9a-f]{16}$/';
public const VALID_TRACE = '/^[0-9a-f]{32}$/';
public const INVALID_SPAN = '0000000000000000';
public const INVALID_TRACE = '00000000000000000000000000000000';
public const SPAN_LENGTH = 16;
public const TRACE_LENGTH = 32;
public const SPAN_LENGTH_BYTES = 8;

/**
* @return bool Returns a value that indicates whether a trace id is valid
*/
public static function isValidTraceId($traceId): bool
{
return ctype_xdigit($traceId) && strlen($traceId) === self::TRACE_LENGTH && $traceId !== self::INVALID_TRACE && $traceId === strtolower($traceId);
}

/**
* @return bool Returns a value that indicates whether a span id is valid
*/
public static function isValidSpanId($spanId): bool
{
return ctype_xdigit($spanId) && strlen($spanId) === self::SPAN_LENGTH && $spanId !== self::INVALID_SPAN && $spanId === strtolower($spanId);
}
}
8 changes: 5 additions & 3 deletions src/Extension/Propagator/B3/B3MultiPropagator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use OpenTelemetry\API\Trace\AbstractSpan;
use OpenTelemetry\API\Trace\SpanContext;
use OpenTelemetry\API\Trace\SpanContextInterface;
use OpenTelemetry\API\Trace\SpanContextValidator;
use OpenTelemetry\Context\Context;
use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter;
use OpenTelemetry\Context\Propagation\PropagationGetterInterface;
Expand Down Expand Up @@ -166,17 +167,18 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter

// Validates the traceId and spanId
// Returns an invalid spanContext if any of the checks fail
if (!SpanContext::isValidTraceId($traceId) || !SpanContext::isValidSpanId($spanId)) {
if (!SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId)) {
return SpanContext::getInvalid();
}

if ($debug && $debug === self::IS_SAMPLED) {
$context = $context->with(B3DebugFlagContextKey::instance(), self::IS_SAMPLED);
$isSampled = SpanContext::SAMPLED_FLAG;
$isSampled = SpanContextInterface::TRACE_FLAG_SAMPLED;
} else {
$isSampled = ($sampled === SpanContext::SAMPLED_FLAG);
$isSampled = ($sampled === SpanContextInterface::TRACE_FLAG_SAMPLED);
}

// Only traceparent header is extracted. No tracestate.
return SpanContext::createFromRemoteParent(
$traceId,
$spanId,
Expand Down
5 changes: 3 additions & 2 deletions src/Extension/Propagator/B3/B3SinglePropagator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use OpenTelemetry\API\Trace\AbstractSpan;
use OpenTelemetry\API\Trace\SpanContext;
use OpenTelemetry\API\Trace\SpanContextInterface;
use OpenTelemetry\API\Trace\SpanContextValidator;
use OpenTelemetry\Context\Context;
use OpenTelemetry\Context\Propagation\ArrayAccessGetterSetter;
use OpenTelemetry\Context\Propagation\PropagationGetterInterface;
Expand Down Expand Up @@ -155,7 +156,7 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter

// Validates the traceId and spanId
// Returns an invalid spanContext if any of the checks fail
if (!SpanContext::isValidTraceId($traceId) || !SpanContext::isValidSpanId($spanId)) {
if (!SpanContextValidator::isValidTraceId($traceId) || !SpanContextValidator::isValidSpanId($spanId)) {
return SpanContext::getInvalid();
}

Expand All @@ -164,7 +165,7 @@ private static function extractImpl($carrier, PropagationGetterInterface $getter
}

$sampled = self::processSampledValue($samplingState);
$isSampled = ($sampled === SpanContext::SAMPLED_FLAG);
$isSampled = ($sampled === SpanContextInterface::TRACE_FLAG_SAMPLED);

return SpanContext::createFromRemoteParent(
$traceId,
Expand Down
6 changes: 3 additions & 3 deletions src/SDK/Trace/RandomIdGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace OpenTelemetry\SDK\Trace;

use OpenTelemetry\API\Trace\SpanContext;
use OpenTelemetry\API\Trace\SpanContextValidator;
use Throwable;

class RandomIdGenerator implements IdGeneratorInterface
Expand All @@ -16,7 +16,7 @@ public function generateTraceId(): string
{
do {
$traceId = $this->randomHex(self::TRACE_ID_HEX_LENGTH);
} while (!SpanContext::isValidTraceId($traceId));
} while (!SpanContextValidator::isValidTraceId($traceId));

return $traceId;
}
Expand All @@ -25,7 +25,7 @@ public function generateSpanId(): string
{
do {
$spanId = $this->randomHex(self::SPAN_ID_HEX_LENGTH);
} while (!SpanContext::isValidSpanId($spanId));
} while (!SpanContextValidator::isValidSpanId($spanId));

return $spanId;
}
Expand Down
5 changes: 3 additions & 2 deletions tests/Integration/SDK/Context/SpanContextTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use OpenTelemetry\API\Trace as API;
use OpenTelemetry\API\Trace\SpanContext;
use OpenTelemetry\API\Trace\SpanContextValidator;
use OpenTelemetry\API\Trace\TraceState;
use OpenTelemetry\SDK\Trace\RandomIdGenerator;
use PHPUnit\Framework\TestCase;
Expand All @@ -21,8 +22,8 @@ class SpanContextTest extends TestCase
public function test_invalid_span(string $traceId, string $spanId): void
{
$spanContext = SpanContext::create($traceId, $spanId);
$this->assertSame(SpanContext::INVALID_TRACE, $spanContext->getTraceId());
$this->assertSame(SpanContext::INVALID_SPAN, $spanContext->getSpanId());
$this->assertSame(SpanContextValidator::INVALID_TRACE, $spanContext->getTraceId());
$this->assertSame(SpanContextValidator::INVALID_SPAN, $spanContext->getSpanId());
}

public function invalidSpanData(): array
Expand Down
Loading