*/ private array $context = []; /** @var array */ private array $contextKeys = []; private function __construct() { self::$spanContextKey = ContextKeys::span(); } public static function createKey(string $key): ContextKeyInterface { return new ContextKey($key); } /** * @param ContextStorageInterface&ExecutionContextAwareInterface $storage */ public static function setStorage(ContextStorageInterface $storage): void { self::$storage = $storage; } /** * @return ContextStorageInterface&ExecutionContextAwareInterface */ public static function storage(): ContextStorageInterface { /** @psalm-suppress RedundantPropertyInitializationCheck */ return self::$storage ??= new ContextStorage(); } /** * @param ContextInterface|false|null $context * * @internal OpenTelemetry */ public static function resolve($context, ?ContextStorageInterface $contextStorage = null): ContextInterface { return $context ?? ($contextStorage ?? self::storage())->current() ?: self::getRoot(); } /** * @internal */ public static function getRoot(): ContextInterface { static $empty; return $empty ??= new self(); } public static function getCurrent(): ContextInterface { return self::storage()->current(); } public function activate(): ScopeInterface { $scope = self::storage()->attach($this); /** @psalm-suppress RedundantCondition */ assert((bool) $scope = new DebugScope($scope)); return $scope; } public function withContextValue(ImplicitContextKeyedInterface $value): ContextInterface { return $value->storeInContext($this); } public function with(ContextKeyInterface $key, $value): self { if ($this->get($key) === $value) { return $this; } $self = clone $this; if ($key === self::$spanContextKey) { $self->span = $value; // @phan-suppress-current-line PhanTypeMismatchPropertyReal return $self; } $id = spl_object_id($key); if ($value !== null) { $self->context[$id] = $value; $self->contextKeys[$id] ??= $key; } else { unset( $self->context[$id], $self->contextKeys[$id], ); } return $self; } public function get(ContextKeyInterface $key) { if ($key === self::$spanContextKey) { /** @psalm-suppress InvalidReturnStatement */ return $this->span; } return $this->context[spl_object_id($key)] ?? null; } }