← All changes
|
vendor_prefixed/sentry/sentry/src/State/RuntimeContextManager.php
+57
-77
1.10.9
→
1.10.22
View file →
| @@ -9,19 +9,16 @@ | ||
| 9 | 9 | use WCPOS\Vendor\Sentry\Tracing\PropagationContext; |
| 10 | 10 | /** |
| 11 | 11 | * Manages runtime-local SDK state across different execution models. |
| 12 | 12 | * |
| 13 | - * Lifecycle model: | |
| 14 | - * - The manager keeps a lazily initialized global context as fallback. | |
| 15 | - * - startContext() creates an isolated runtime context for the current | |
| 16 | - * execution key when no context is active yet. | |
| 17 | - * - endContext() flushes context resources and removes that context. | |
| 13 | + * The manager keeps a lazily initialized global context as fallback. Explicit | |
| 14 | + * contexts use process-local storage by default, or the configured storage for | |
| 15 | + * runtimes with overlapping logical executions. | |
| 18 | 16 | * |
| 19 | 17 | * @internal |
| 20 | 18 | */ |
| 21 | 19 | final class RuntimeContextManager |
| 22 | 20 | { |
| 23 | - private const PROCESS_EXECUTION_CONTEXT_KEY = 'process'; | |
| 24 | 21 | /** |
| 25 | 22 | * @var HubInterface |
| 26 | 23 | */ |
| 27 | 24 | private $baseHub; |
| @@ -29,24 +26,24 @@ | ||
| 29 | 26 | * @var RuntimeContext|null |
| 30 | 27 | */ |
| 31 | 28 | private $globalContext; |
| 32 | 29 | /** |
| 33 | - * @var array<string, RuntimeContext> | |
| 30 | + * @var RuntimeContext|null | |
| 34 | 31 | */ |
| 35 | - private $activeContexts = []; | |
| 32 | + private $runtimeContext; | |
| 36 | 33 | /** |
| 37 | - * @var array<string, string> | |
| 34 | + * @var RuntimeContextStorageInterface|null | |
| 38 | 35 | */ |
| 39 | - private $executionContextToRuntimeContext = []; | |
| 40 | - public function __construct(HubInterface $baseHub) | |
| 36 | + private $runtimeContextStorage; | |
| 37 | + public function __construct(HubInterface $baseHub, ?RuntimeContextStorageInterface $runtimeContextStorage = null) | |
| 41 | 38 | { |
| 42 | 39 | $this->baseHub = $baseHub; |
| 43 | - $this->globalContext = null; | |
| 40 | + $this->runtimeContextStorage = $runtimeContextStorage; | |
| 44 | 41 | } |
| 45 | 42 | /** |
| 46 | 43 | * Sets the current hub with context-aware behavior. |
| 47 | 44 | * |
| 48 | - * If a runtime context is active for the current execution key, the hub is | |
| 45 | + * If a runtime context is active for the current logical execution, the hub is | |
| 49 | 46 | * updated only for that active context. Otherwise, the baseline/global hub |
| 50 | 47 | * template is updated. |
| 51 | 48 | * |
| 52 | 49 | * @return bool Whether the hub was set on an active runtime context |
| @@ -52,12 +49,11 @@ | ||
| 52 | 49 | * @return bool Whether the hub was set on an active runtime context |
| 53 | 50 | */ |
| 54 | 51 | public function setCurrentHub(HubInterface $hub) : bool |
| 55 | 52 | { |
| 56 | - $executionContextKey = $this->getExecutionContextKey(); | |
| 57 | - if ($this->hasActiveContextForExecutionContextKey($executionContextKey)) { | |
| 58 | - $runtimeContextId = $this->executionContextToRuntimeContext[$executionContextKey]; | |
| 59 | - $this->activeContexts[$runtimeContextId]->setHub($hub); | |
| 53 | + $runtimeContext = $this->getActiveContext(); | |
| 54 | + if ($runtimeContext !== null) { | |
| 55 | + $runtimeContext->setHub($hub); | |
| 60 | 56 | return \true; |
| 61 | 57 | } |
| 62 | 58 | $this->baseHub = $hub; |
| 63 | 59 | if ($this->globalContext !== null) { |
| @@ -70,66 +66,52 @@ | ||
| 70 | 66 | return $this->getCurrentContext()->getHub(); |
| 71 | 67 | } |
| 72 | 68 | public function getCurrentContext() : RuntimeContext |
| 73 | 69 | { |
| 74 | - $executionContextKey = $this->getExecutionContextKey(); | |
| 75 | - if ($this->hasActiveContextForExecutionContextKey($executionContextKey)) { | |
| 76 | - $runtimeContextId = $this->executionContextToRuntimeContext[$executionContextKey]; | |
| 77 | - return $this->activeContexts[$runtimeContextId]; | |
| 78 | - } | |
| 79 | - return $this->getGlobalContext(); | |
| 70 | + return $this->getActiveContext() ?? $this->getGlobalContext(); | |
| 80 | 71 | } |
| 81 | - public function hasActiveContext() : bool | |
| 82 | - { | |
| 83 | - return $this->hasActiveContextForExecutionContextKey($this->getExecutionContextKey()); | |
| 84 | - } | |
| 85 | 72 | /** |
| 86 | - * Starts an isolated context for the current execution key. | |
| 73 | + * Starts an isolated context for the current logical execution. | |
| 74 | + * | |
| 75 | + * A provided hub is used as-is. It is ignored when a context is already active. | |
| 76 | + * | |
| 77 | + * @param HubInterface|null $hub The hub to use for the new context | |
| 78 | + * | |
| 79 | + * @return bool Whether a new context was started | |
| 87 | 80 | */ |
| 88 | - public function startContext() : void | |
| 81 | + public function startContext(?HubInterface $hub = null) : bool | |
| 89 | 82 | { |
| 90 | - $executionContextKey = $this->getExecutionContextKey(); | |
| 91 | - if ($this->hasActiveContextForExecutionContextKey($executionContextKey)) { | |
| 92 | - // Nested start calls for the same execution key should be a no-op. | |
| 93 | - return; | |
| 83 | + if ($this->getActiveContext() !== null) { | |
| 84 | + // Nested start calls for the same logical execution should be a no-op. | |
| 85 | + return \false; | |
| 94 | 86 | } |
| 95 | 87 | ErrorHandler::resetFatalErrorHandlerState(); |
| 96 | - $this->createContextForExecutionContextKey($executionContextKey); | |
| 88 | + $this->setActiveContext(new RuntimeContext($this->generateRuntimeContextId(), $hub ?? $this->createHubFromBaseHub())); | |
| 89 | + return \true; | |
| 97 | 90 | } |
| 98 | 91 | /** |
| 99 | - * Ends and flushes the active context for the current execution key. | |
| 92 | + * Ends and flushes the active context for the current logical execution. | |
| 100 | 93 | * |
| 101 | - * When no context is active for the key this is a no-op. | |
| 94 | + * When no context is active this is a no-op. | |
| 95 | + * | |
| 96 | + * @param int|null $timeout The maximum number of seconds to wait while flushing the client transport | |
| 102 | 97 | */ |
| 103 | 98 | public function endContext(?int $timeout = null) : void |
| 104 | 99 | { |
| 105 | - $executionContextKey = $this->getExecutionContextKey(); | |
| 106 | - if (!$this->hasActiveContextForExecutionContextKey($executionContextKey)) { | |
| 100 | + $runtimeContext = $this->removeActiveContext(); | |
| 101 | + if ($runtimeContext === null) { | |
| 107 | 102 | return; |
| 108 | 103 | } |
| 109 | - $runtimeContextId = $this->executionContextToRuntimeContext[$executionContextKey]; | |
| 110 | - unset($this->executionContextToRuntimeContext[$executionContextKey]); | |
| 111 | - $this->removeContextById($runtimeContextId, $timeout); | |
| 104 | + $logger = $this->getLoggerFromHub($runtimeContext->getHub()); | |
| 105 | + $this->flushRuntimeContextResources($runtimeContext, $timeout, $logger); | |
| 112 | 106 | } |
| 113 | - private function createContextForExecutionContextKey(string $executionContextKey) : void | |
| 107 | + /** | |
| 108 | + * Discards the active context for the current logical execution without flushing it. | |
| 109 | + */ | |
| 110 | + public function discardActiveContext() : void | |
| 114 | 111 | { |
| 115 | - $runtimeContextId = $this->generateRuntimeContextId(); | |
| 116 | - $runtimeContext = new RuntimeContext($runtimeContextId, $this->createHubFromBaseHub()); | |
| 117 | - $this->activeContexts[$runtimeContextId] = $runtimeContext; | |
| 118 | - $this->executionContextToRuntimeContext[$executionContextKey] = $runtimeContextId; | |
| 112 | + $this->removeActiveContext(); | |
| 119 | 113 | } |
| 120 | - private function removeContextById(string $runtimeContextId, ?int $timeout = null) : void | |
| 121 | - { | |
| 122 | - if (!isset($this->activeContexts[$runtimeContextId])) { | |
| 123 | - return; | |
| 124 | - } | |
| 125 | - $runtimeContext = $this->activeContexts[$runtimeContextId]; | |
| 126 | - unset($this->activeContexts[$runtimeContextId]); | |
| 127 | - // Remove any key mappings that may still reference this context. | |
| 128 | - $this->removeExecutionContextMappingsForRuntimeContext($runtimeContextId); | |
| 129 | - $logger = $this->getLoggerFromHub($runtimeContext->getHub()); | |
| 130 | - $this->flushRuntimeContextResources($runtimeContext, $timeout, $logger); | |
| 131 | - } | |
| 132 | 114 | private function flushRuntimeContextResources(RuntimeContext $runtimeContext, ?int $timeout, LoggerInterface $logger) : void |
| 133 | 115 | { |
| 134 | 116 | $hub = $runtimeContext->getHub(); |
| 135 | 117 | // captureEvent can throw before transport send (for example from scope event processors |
| @@ -155,28 +137,31 @@ | ||
| 155 | 137 | } catch (\Throwable $exception) { |
| 156 | 138 | $logger->error('Failed to flush the client transport while ending a runtime context.', ['exception' => $exception, 'runtime_context_id' => $runtimeContext->getId()]); |
| 157 | 139 | } |
| 158 | 140 | } |
| 159 | - private function removeExecutionContextMappingsForRuntimeContext(string $runtimeContextId) : void | |
| 141 | + private function getActiveContext() : ?RuntimeContext | |
| 160 | 142 | { |
| 161 | - foreach ($this->executionContextToRuntimeContext as $executionContextKey => $mappedRuntimeContextId) { | |
| 162 | - if ($mappedRuntimeContextId === $runtimeContextId) { | |
| 163 | - unset($this->executionContextToRuntimeContext[$executionContextKey]); | |
| 164 | - } | |
| 143 | + if ($this->runtimeContextStorage !== null) { | |
| 144 | + return $this->runtimeContextStorage->get(); | |
| 165 | 145 | } |
| 146 | + return $this->runtimeContext; | |
| 166 | 147 | } |
| 167 | - private function hasActiveContextForExecutionContextKey(string $executionContextKey) : bool | |
| 148 | + private function setActiveContext(RuntimeContext $runtimeContext) : void | |
| 168 | 149 | { |
| 169 | - if (!isset($this->executionContextToRuntimeContext[$executionContextKey])) { | |
| 170 | - return \false; | |
| 150 | + if ($this->runtimeContextStorage !== null) { | |
| 151 | + $this->runtimeContextStorage->set($runtimeContext); | |
| 152 | + return; | |
| 171 | 153 | } |
| 172 | - $runtimeContextId = $this->executionContextToRuntimeContext[$executionContextKey]; | |
| 173 | - if (!isset($this->activeContexts[$runtimeContextId])) { | |
| 174 | - // Mapping points to a context that was already evicted/ended; drop the stale index entry. | |
| 175 | - unset($this->executionContextToRuntimeContext[$executionContextKey]); | |
| 176 | - return \false; | |
| 154 | + $this->runtimeContext = $runtimeContext; | |
| 155 | + } | |
| 156 | + private function removeActiveContext() : ?RuntimeContext | |
| 157 | + { | |
| 158 | + if ($this->runtimeContextStorage !== null) { | |
| 159 | + return $this->runtimeContextStorage->remove(); | |
| 177 | 160 | } |
| 178 | - return \true; | |
| 161 | + $runtimeContext = $this->runtimeContext; | |
| 162 | + $this->runtimeContext = null; | |
| 163 | + return $runtimeContext; | |
| 179 | 164 | } |
| 180 | 165 | private function createHubFromBaseHub() : HubInterface |
| 181 | 166 | { |
| 182 | 167 | if (!$this->baseHub instanceof Hub) { |
| @@ -201,13 +186,8 @@ | ||
| 201 | 186 | } |
| 202 | 187 | private function generateRuntimeContextId() : string |
| 203 | 188 | { |
| 204 | 189 | return \sprintf('%s-%d', \str_replace('.', '', \uniqid('', \true)), \mt_rand()); |
| 205 | - } | |
| 206 | - private function getExecutionContextKey() : string | |
| 207 | - { | |
| 208 | - // All supported runtime modes currently use a process-local execution key. | |
| 209 | - return self::PROCESS_EXECUTION_CONTEXT_KEY; | |
| 210 | 190 | } |
| 211 | 191 | private function getGlobalContext() : RuntimeContext |
| 212 | 192 | { |
| 213 | 193 | if ($this->globalContext === null) { |