PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.10
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.10
1.10.25 1.10.24 1.10.23 1.10.22 1.10.21 1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 All 169 releases
woocommerce-pos / vendor_prefixed / sentry / sentry / src / State / RuntimeContextManager.php

RuntimeContextManager.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.10, at vendor_prefixed/sentry/sentry/src/State/RuntimeContextManager.php

220 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace WCPOS\Vendor\Sentry\State;
5
6 use WCPOS\Vendor\Psr\Log\LoggerInterface;
7 use WCPOS\Vendor\Psr\Log\NullLogger;
8 use WCPOS\Vendor\Sentry\ErrorHandler;
9 use WCPOS\Vendor\Sentry\Tracing\PropagationContext;
10 /**
11 * Manages runtime-local SDK state across different execution models.
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.
18 *
19 * @internal
20 */
21 final class RuntimeContextManager
22 {
23 private const PROCESS_EXECUTION_CONTEXT_KEY = 'process';
24 /**
25 * @var HubInterface
26 */
27 private $baseHub;
28 /**
29 * @var RuntimeContext|null
30 */
31 private $globalContext;
32 /**
33 * @var array<string, RuntimeContext>
34 */
35 private $activeContexts = [];
36 /**
37 * @var array<string, string>
38 */
39 private $executionContextToRuntimeContext = [];
40 public function __construct(HubInterface $baseHub)
41 {
42 $this->baseHub = $baseHub;
43 $this->globalContext = null;
44 }
45 /**
46 * Sets the current hub with context-aware behavior.
47 *
48 * If a runtime context is active for the current execution key, the hub is
49 * updated only for that active context. Otherwise, the baseline/global hub
50 * template is updated.
51 *
52 * @return bool Whether the hub was set on an active runtime context
53 */
54 public function setCurrentHub(HubInterface $hub) : bool
55 {
56 $executionContextKey = $this->getExecutionContextKey();
57 if ($this->hasActiveContextForExecutionContextKey($executionContextKey)) {
58 $runtimeContextId = $this->executionContextToRuntimeContext[$executionContextKey];
59 $this->activeContexts[$runtimeContextId]->setHub($hub);
60 return \true;
61 }
62 $this->baseHub = $hub;
63 if ($this->globalContext !== null) {
64 $this->globalContext->setHub($hub);
65 }
66 return \false;
67 }
68 public function getCurrentHub() : HubInterface
69 {
70 return $this->getCurrentContext()->getHub();
71 }
72 public function getCurrentContext() : RuntimeContext
73 {
74 $executionContextKey = $this->getExecutionContextKey();
75 if ($this->hasActiveContextForExecutionContextKey($executionContextKey)) {
76 $runtimeContextId = $this->executionContextToRuntimeContext[$executionContextKey];
77 return $this->activeContexts[$runtimeContextId];
78 }
79 return $this->getGlobalContext();
80 }
81 public function hasActiveContext() : bool
82 {
83 return $this->hasActiveContextForExecutionContextKey($this->getExecutionContextKey());
84 }
85 /**
86 * Starts an isolated context for the current execution key.
87 */
88 public function startContext() : void
89 {
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;
94 }
95 ErrorHandler::resetFatalErrorHandlerState();
96 $this->createContextForExecutionContextKey($executionContextKey);
97 }
98 /**
99 * Ends and flushes the active context for the current execution key.
100 *
101 * When no context is active for the key this is a no-op.
102 */
103 public function endContext(?int $timeout = null) : void
104 {
105 $executionContextKey = $this->getExecutionContextKey();
106 if (!$this->hasActiveContextForExecutionContextKey($executionContextKey)) {
107 return;
108 }
109 $runtimeContextId = $this->executionContextToRuntimeContext[$executionContextKey];
110 unset($this->executionContextToRuntimeContext[$executionContextKey]);
111 $this->removeContextById($runtimeContextId, $timeout);
112 }
113 private function createContextForExecutionContextKey(string $executionContextKey) : void
114 {
115 $runtimeContextId = $this->generateRuntimeContextId();
116 $runtimeContext = new RuntimeContext($runtimeContextId, $this->createHubFromBaseHub());
117 $this->activeContexts[$runtimeContextId] = $runtimeContext;
118 $this->executionContextToRuntimeContext[$executionContextKey] = $runtimeContextId;
119 }
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 private function flushRuntimeContextResources(RuntimeContext $runtimeContext, ?int $timeout, LoggerInterface $logger) : void
133 {
134 $hub = $runtimeContext->getHub();
135 // captureEvent can throw before transport send (for example from scope event processors
136 // or before_send callbacks), so we isolate failures and continue flushing other resources.
137 try {
138 $runtimeContext->getLogsAggregator()->flush($hub);
139 } catch (\Throwable $exception) {
140 $logger->error('Failed to flush logs while ending a runtime context.', ['exception' => $exception, 'runtime_context_id' => $runtimeContext->getId()]);
141 }
142 // Keep metrics flush independent from logs flush so one bad callback does not block the rest.
143 try {
144 $runtimeContext->getMetricsAggregator()->flush($hub);
145 } catch (\Throwable $exception) {
146 $logger->error('Failed to flush trace metrics while ending a runtime context.', ['exception' => $exception, 'runtime_context_id' => $runtimeContext->getId()]);
147 }
148 $client = $hub->getClient();
149 if ($client === null) {
150 return;
151 }
152 // Custom transports may throw from close(); endContext must stay best-effort and non-fatal.
153 try {
154 $client->flush($timeout);
155 } catch (\Throwable $exception) {
156 $logger->error('Failed to flush the client transport while ending a runtime context.', ['exception' => $exception, 'runtime_context_id' => $runtimeContext->getId()]);
157 }
158 }
159 private function removeExecutionContextMappingsForRuntimeContext(string $runtimeContextId) : void
160 {
161 foreach ($this->executionContextToRuntimeContext as $executionContextKey => $mappedRuntimeContextId) {
162 if ($mappedRuntimeContextId === $runtimeContextId) {
163 unset($this->executionContextToRuntimeContext[$executionContextKey]);
164 }
165 }
166 }
167 private function hasActiveContextForExecutionContextKey(string $executionContextKey) : bool
168 {
169 if (!isset($this->executionContextToRuntimeContext[$executionContextKey])) {
170 return \false;
171 }
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;
177 }
178 return \true;
179 }
180 private function createHubFromBaseHub() : HubInterface
181 {
182 if (!$this->baseHub instanceof Hub) {
183 return new Hub($this->baseHub->getClient());
184 }
185 $clonedScope = null;
186 $this->baseHub->configureScope(static function (Scope $scope) use(&$clonedScope) : void {
187 $clonedScope = clone $scope;
188 // Do not inherit active traces into a new runtime context.
189 $clonedScope->setSpan(null);
190 $clonedScope->setPropagationContext(PropagationContext::fromDefaults());
191 });
192 return new Hub($this->baseHub->getClient(), $clonedScope ?? new Scope());
193 }
194 private function getLoggerFromHub(HubInterface $hub) : LoggerInterface
195 {
196 $client = $hub->getClient();
197 if ($client === null) {
198 return new NullLogger();
199 }
200 return $client->getOptions()->getLoggerOrNullLogger();
201 }
202 private function generateRuntimeContextId() : string
203 {
204 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 }
211 private function getGlobalContext() : RuntimeContext
212 {
213 if ($this->globalContext === null) {
214 // Lazy fallback keeps baseline behavior when users do not opt into explicit context lifecycle.
215 $this->globalContext = new RuntimeContext('global', $this->baseHub);
216 }
217 return $this->globalContext;
218 }
219 }
220