tracestate + baggage todos (#894)

- remove baggage TODOs which have since been done.
- implement TODOs from tracestate to log warnings.
- tidy up tracestate code, simplify some const names.
This commit is contained in:
Brett McBride 2022-12-12 14:16:41 +11:00 committed by GitHub
parent 602ea8539f
commit 616b356b83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 41 deletions

View File

@ -16,8 +16,6 @@ interface BaggageInterface extends ImplicitContextKeyedInterface
/** /**
* Returns the {@see API\BaggageInterface} from the provided *$context*, * Returns the {@see API\BaggageInterface} from the provided *$context*,
* falling back on {@see API\BaggageInterface::getEmpty()} if there is no baggage in the provided context. * falling back on {@see API\BaggageInterface::getEmpty()} if there is no baggage in the provided context.
*
* @todo Implement this in the API layer
*/ */
public static function fromContext(ContextInterface $context): API\BaggageInterface; public static function fromContext(ContextInterface $context): API\BaggageInterface;
@ -29,8 +27,6 @@ interface BaggageInterface extends ImplicitContextKeyedInterface
/** /**
* Returns the current {@see Baggage} from the current {@see ContextInterface}, * Returns the current {@see Baggage} from the current {@see ContextInterface},
* falling back on {@see API\BaggageInterface::getEmpty()} if there is no baggage in the current context. * falling back on {@see API\BaggageInterface::getEmpty()} if there is no baggage in the current context.
*
* @todo Implement this in the API layer
*/ */
public static function getCurrent(): API\BaggageInterface; public static function getCurrent(): API\BaggageInterface;

View File

@ -5,12 +5,15 @@ declare(strict_types=1);
namespace OpenTelemetry\API\Trace; namespace OpenTelemetry\API\Trace;
use function array_reverse; use function array_reverse;
use OpenTelemetry\API\Behavior\LogsMessagesTrait;
use function strlen; use function strlen;
class TraceState implements TraceStateInterface class TraceState implements TraceStateInterface
{ {
public const MAX_TRACESTATE_LIST_MEMBERS = 32; use LogsMessagesTrait;
public const MAX_TRACESTATE_LENGTH = 512;
public const MAX_LIST_MEMBERS = 32; //@see https://www.w3.org/TR/trace-context/#tracestate-header-field-values
public const MAX_COMBINED_LENGTH = 512; //@see https://www.w3.org/TR/trace-context/#tracestate-limits
public const LIST_MEMBERS_SEPARATOR = ','; public const LIST_MEMBERS_SEPARATOR = ',';
public const LIST_MEMBER_KEY_VALUE_SPLITTER = '='; public const LIST_MEMBER_KEY_VALUE_SPLITTER = '=';
private const VALID_KEY_CHAR_RANGE = '[_0-9a-z-*\/]'; private const VALID_KEY_CHAR_RANGE = '[_0-9a-z-*\/]';
@ -39,7 +42,6 @@ class TraceState implements TraceStateInterface
{ {
$clonedTracestate = clone $this; $clonedTracestate = clone $this;
//TODO: Log if we can't set the value
if ($this->validateKey($key) && $this->validateValue($value)) { if ($this->validateKey($key) && $this->validateValue($value)) {
/* /*
@ -54,6 +56,8 @@ class TraceState implements TraceStateInterface
// Add new or updated entry to the back of the list. // Add new or updated entry to the back of the list.
$clonedTracestate->traceState[$key] = $value; $clonedTracestate->traceState[$key] = $value;
} else {
self::logWarning('Invalid tracetrace key/value for: ' . $key);
} }
return $clonedTracestate; return $clonedTracestate;
@ -66,7 +70,6 @@ class TraceState implements TraceStateInterface
{ {
$clonedTracestate = clone $this; $clonedTracestate = clone $this;
//TODO: Log if we can't unset the value
if ($key !== '') { if ($key !== '') {
unset($clonedTracestate->traceState[$key]); unset($clonedTracestate->traceState[$key]);
} }
@ -123,36 +126,30 @@ class TraceState implements TraceStateInterface
*/ */
private function parse(string $rawTracestate): array private function parse(string $rawTracestate): array
{ {
$parsedTracestate = []; if (strlen($rawTracestate) > self::MAX_COMBINED_LENGTH) {
self::logWarning('tracestate discarded, exceeds max combined length: ' . self::MAX_COMBINED_LENGTH);
if (strlen($rawTracestate) <= self::MAX_TRACESTATE_LENGTH) { return [];
}
$parsedTracestate = [];
$listMembers = explode(self::LIST_MEMBERS_SEPARATOR, $rawTracestate); $listMembers = explode(self::LIST_MEMBERS_SEPARATOR, $rawTracestate);
// Discard tracestate if entries exceed max length. if (count($listMembers) > self::MAX_LIST_MEMBERS) {
if (count($listMembers) > self::MAX_TRACESTATE_LIST_MEMBERS) { self::logWarning('tracestate discarded, too many members');
// TODO: Log a message when we discard.
return []; return [];
} }
$invalid = false;
foreach ($listMembers as $listMember) { foreach ($listMembers as $listMember) {
$vendor = explode(self::LIST_MEMBER_KEY_VALUE_SPLITTER, trim($listMember)); $vendor = explode(self::LIST_MEMBER_KEY_VALUE_SPLITTER, trim($listMember));
// There should only be one list-member per vendor separated by '=' // There should only be one list-member per vendor separated by '='
// TODO: Log if we can't validate the key and value if (count($vendor) !== 2 || !$this->validateKey($vendor[0]) || !$this->validateValue($vendor[1])) {
if (count($vendor) === 2 && ($this->validateKey($vendor[0]) && $this->validateValue($vendor[1]))) { self::logWarning('tracestate discarded, invalid member: ' . $listMember);
$parsedTracestate[$vendor[0]] = $vendor[1];
continue;
}
$invalid = true;
break;
}
// Discard tracestate if any member is invalid.
if ($invalid) {
return []; return [];
} }
$parsedTracestate[$vendor[0]] = $vendor[1];
} }
/* /*

View File

@ -75,7 +75,7 @@ class TraceStateTest extends TestCase
public function test_max_tracestate_list_members(): void public function test_max_tracestate_list_members(): void
{ {
// Build a tracestate with the max 32 values. Ex '0=0,1=1,...,31=31' // Build a tracestate with the max 32 values. Ex '0=0,1=1,...,31=31'
$rawTraceState = range(0, TraceState::MAX_TRACESTATE_LIST_MEMBERS - 1); $rawTraceState = range(0, TraceState::MAX_LIST_MEMBERS - 1);
array_walk($rawTraceState, static function (&$v, $k) { array_walk($rawTraceState, static function (&$v, $k) {
$v = 'k' . $k . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . 'v' . $v; $v = 'k' . $k . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . 'v' . $v;
}); });
@ -84,14 +84,14 @@ class TraceStateTest extends TestCase
* @var array $rawTraceState * @var array $rawTraceState
* @see https://github.com/vimeo/psalm/issues/6394 * @see https://github.com/vimeo/psalm/issues/6394
*/ */
$this->assertCount(TraceState::MAX_TRACESTATE_LIST_MEMBERS, $rawTraceState); $this->assertCount(TraceState::MAX_LIST_MEMBERS, $rawTraceState);
$validTracestate = new TraceState(implode(TraceState::LIST_MEMBERS_SEPARATOR, $rawTraceState)); $validTracestate = new TraceState(implode(TraceState::LIST_MEMBERS_SEPARATOR, $rawTraceState));
$this->assertSame(TraceState::MAX_TRACESTATE_LIST_MEMBERS, $validTracestate->getListMemberCount()); $this->assertSame(TraceState::MAX_LIST_MEMBERS, $validTracestate->getListMemberCount());
// Add a list-member to the tracestate that exceeds the max of 32. This will cause the tracestate to be discarded. // Add a list-member to the tracestate that exceeds the max of 32. This will cause the tracestate to be discarded.
$rawTraceState[32] = 'k32' . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . 'v32'; $rawTraceState[32] = 'k32' . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . 'v32';
$this->assertCount(TraceState::MAX_TRACESTATE_LIST_MEMBERS + 1, $rawTraceState); $this->assertCount(TraceState::MAX_LIST_MEMBERS + 1, $rawTraceState);
$truncatedTracestate = new TraceState(implode(TraceState::LIST_MEMBERS_SEPARATOR, $rawTraceState)); $truncatedTracestate = new TraceState(implode(TraceState::LIST_MEMBERS_SEPARATOR, $rawTraceState));
$this->assertSame(0, $truncatedTracestate->getListMemberCount()); $this->assertSame(0, $truncatedTracestate->getListMemberCount());
@ -100,21 +100,21 @@ class TraceStateTest extends TestCase
public function test_max_tracestate_length(): void public function test_max_tracestate_length(): void
{ {
// Build a vendor key with a length of 256 characters. The max characters allowed. // Build a vendor key with a length of 256 characters. The max characters allowed.
$vendorKey = str_repeat('k', TraceState::MAX_TRACESTATE_LENGTH / 2); $vendorKey = str_repeat('k', TraceState::MAX_COMBINED_LENGTH / 2);
// Build a vendor value with a length of 255 characters. One below the max allowed. // Build a vendor value with a length of 255 characters. One below the max allowed.
$vendorValue = str_repeat('v', TraceState::MAX_TRACESTATE_LENGTH / 2 - 1); $vendorValue = str_repeat('v', TraceState::MAX_COMBINED_LENGTH / 2 - 1);
// tracestate length = 513 characters (not accepted). // tracestate length = 513 characters (not accepted).
$rawTraceState = $vendorKey . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . $vendorValue . 'v'; $rawTraceState = $vendorKey . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . $vendorValue . 'v';
$this->assertGreaterThan(TraceState::MAX_TRACESTATE_LENGTH, strlen($rawTraceState)); $this->assertGreaterThan(TraceState::MAX_COMBINED_LENGTH, strlen($rawTraceState));
$validTracestate = new TraceState($rawTraceState); $validTracestate = new TraceState($rawTraceState);
$this->assertNull($validTracestate->get($vendorKey)); $this->assertNull($validTracestate->get($vendorKey));
// tracestate length = 512 characters (accepted). // tracestate length = 512 characters (accepted).
$rawTraceState = $vendorKey . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . $vendorValue; $rawTraceState = $vendorKey . TraceState::LIST_MEMBER_KEY_VALUE_SPLITTER . $vendorValue;
$this->assertSame(TraceState::MAX_TRACESTATE_LENGTH, strlen($rawTraceState)); $this->assertSame(TraceState::MAX_COMBINED_LENGTH, strlen($rawTraceState));
$validTracestate = new TraceState($rawTraceState); $validTracestate = new TraceState($rawTraceState);
$this->assertSame($rawTraceState, (string) $validTracestate); $this->assertSame($rawTraceState, (string) $validTracestate);