From 450ebcc6edbb03e55ba018dc447a37c5a98e0377 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:26:25 +0800 Subject: [PATCH 1/4] refactor(sentry): optimize SingletonAspect with match expression for class handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the complex closure-based singleton instance reset logic with a more efficient match expression that explicitly handles different Sentry class types: - Direct instantiation for singleton classes (HubAdapter, IntegrationRegistry) - Simplified TraceMetrics creation - Bypass context handling for enum types - Default to original behavior for unknown classes This improves performance, readability, and reduces the overhead of reflection-based property manipulation while maintaining coroutine safety through Context. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/sentry/src/Aspect/SingletonAspect.php | 40 +++++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/sentry/src/Aspect/SingletonAspect.php b/src/sentry/src/Aspect/SingletonAspect.php index e022d229f..1805944ae 100644 --- a/src/sentry/src/Aspect/SingletonAspect.php +++ b/src/sentry/src/Aspect/SingletonAspect.php @@ -37,26 +37,30 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $key = $className = $proceedingJoinPoint->className; $arguments = $proceedingJoinPoint->getArguments(); - if (isset($arguments[0])) { + if (! empty($arguments)) { $key .= '#' . $arguments[0]; } - return Context::getOrSet($key, function () use ($proceedingJoinPoint, $className, $arguments) { - // Reset singleton instance before proceeding - Closure::bind(function () use ($className, $arguments) { - if (property_exists($className, 'instance')) { - $className::$instance = null; - } elseif ( - property_exists($className, 'instances') - && isset($arguments[0]) - && array_key_exists($arguments[0], $className::$instances) - ) { - $className::$instances[$arguments[0]] = null; - } - }, null, $className)(); - - // Proceed to get the singleton instance - return $proceedingJoinPoint->process(); - }); + return match ($className) { + // Singleton Classes + \Sentry\State\HubAdapter::class, + \Sentry\Integration\IntegrationRegistry::class => Context::getOrSet($key, function () use ($className) { + return Closure::bind(fn () => new $className(), null, $className)(); + }), + \Sentry\Metrics\TraceMetrics::class => Context::getOrSet($key, function () use ($className) { + return new $className(); + }), + + // Enums + \Sentry\CheckInStatus::class, + \Sentry\EventType::class, + \Sentry\MonitorScheduleUnit::class, + \Sentry\Logs\LogLevel::class, + \Sentry\Tracing\SpanStatus::class, + \Sentry\Tracing\TransactionSource::class, + \Sentry\Transport\ResultStatus::class, + \Sentry\Unit::class => $proceedingJoinPoint->process(), + default => $proceedingJoinPoint->process(), + }; } } From ff15010c5abe0a873af7e67c2731919b6d3a9a67 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:54:53 +0800 Subject: [PATCH 2/4] refactor(sentry): replace Co::defer with defer function for coroutine handling --- src/sentry/src/Aspect/CoroutineAspect.php | 6 ++++-- src/sentry/src/Metrics/Aspect/HistogramAspect.php | 4 ++-- src/sentry/src/Metrics/Listener/RequestWatcher.php | 5 +++-- src/sentry/src/Tracing/Aspect/CoroutineAspect.php | 3 ++- .../src/Tracing/Listener/EventHandleListener.php | 12 ++++++------ src/sentry/src/Tracing/Tracer.php | 3 ++- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/sentry/src/Aspect/CoroutineAspect.php b/src/sentry/src/Aspect/CoroutineAspect.php index 188950dc3..a38865a3e 100644 --- a/src/sentry/src/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Aspect/CoroutineAspect.php @@ -19,6 +19,8 @@ use Sentry\SentrySdk; use Throwable; +use function Hyperf\Coroutine\defer; + class CoroutineAspect extends AbstractAspect { public const CONTEXT_KEYS = [ @@ -58,7 +60,7 @@ protected function handleCreate(ProceedingJoinPoint $proceedingJoinPoint): void } // Defer the flushing of events until the coroutine completes. - Co::defer(fn () => Integration::flushEvents()); + defer(fn () => Integration::flushEvents()); // Continue the callable in the new Coroutine. $callable(); @@ -73,6 +75,6 @@ protected function handlePrintLog(ProceedingJoinPoint $proceedingJoinPoint): voi return; } - Co::defer(fn () => SentrySdk::getCurrentHub()->captureException($throwable)); + defer(fn () => SentrySdk::getCurrentHub()->captureException($throwable)); } } diff --git a/src/sentry/src/Metrics/Aspect/HistogramAspect.php b/src/sentry/src/Metrics/Aspect/HistogramAspect.php index 452db7dbf..50845cf19 100644 --- a/src/sentry/src/Metrics/Aspect/HistogramAspect.php +++ b/src/sentry/src/Metrics/Aspect/HistogramAspect.php @@ -16,8 +16,8 @@ use FriendsOfHyperf\Sentry\Metrics\Timer; use Hyperf\Di\Aop\AbstractAspect; use Hyperf\Di\Aop\ProceedingJoinPoint; -use Hyperf\Engine\Coroutine as Co; +use function Hyperf\Coroutine\defer; use function Hyperf\Tappable\tap; class HistogramAspect extends AbstractAspect @@ -54,7 +54,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint): mixed ]); return tap($proceedingJoinPoint->process(), function () use ($timer) { - Co::defer(fn () => $timer->end(true)); + defer(fn () => $timer->end(true)); }); } diff --git a/src/sentry/src/Metrics/Listener/RequestWatcher.php b/src/sentry/src/Metrics/Listener/RequestWatcher.php index a6679b93f..a828d1e1d 100644 --- a/src/sentry/src/Metrics/Listener/RequestWatcher.php +++ b/src/sentry/src/Metrics/Listener/RequestWatcher.php @@ -14,13 +14,14 @@ use FriendsOfHyperf\Sentry\Feature; use FriendsOfHyperf\Sentry\Metrics\CoroutineServerStats; use FriendsOfHyperf\Sentry\Metrics\Timer; -use Hyperf\Engine\Coroutine as Co; use Hyperf\Event\Contract\ListenerInterface; use Hyperf\HttpServer\Event as HttpEvent; use Hyperf\HttpServer\Router\Dispatched; use Hyperf\RpcServer\Event as RpcEvent; use Psr\Http\Message\ServerRequestInterface; +use function Hyperf\Coroutine\defer; + class RequestWatcher implements ListenerInterface { public function __construct( @@ -56,7 +57,7 @@ public function process(object $event): void 'request_method' => $request->getMethod(), ]); - Co::defer(function () use ($timer) { + defer(function () use ($timer) { ++$this->stats->close_count; ++$this->stats->response_count; --$this->stats->connection_num; diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index f3c58fa82..bc0170170 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -25,6 +25,7 @@ use function FriendsOfHyperf\Sentry\startTransaction; use function FriendsOfHyperf\Sentry\trace; +use function Hyperf\Coroutine\defer; use function Sentry\continueTrace; class CoroutineAspect extends AbstractAspect @@ -82,7 +83,7 @@ function (Scope $scope) use ($proceedingJoinPoint, $callingOnFunction) { ); // Defer the finishing of the transaction and flushing of events until the coroutine completes. - Co::defer(function () use ($transaction) { + defer(function () use ($transaction) { $transaction->finish(); Integration::flushEvents(); }); diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index b88191973..8d0df8b08 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -29,7 +29,6 @@ use Hyperf\Crontab\Event as CrontabEvent; use Hyperf\Database\Events as DbEvent; use Hyperf\DbConnection\Pool\PoolFactory; -use Hyperf\Engine\Coroutine as Co; use Hyperf\Event\Contract\ListenerInterface; use Hyperf\HttpServer\Event as HttpEvent; use Hyperf\HttpServer\Router\Dispatched; @@ -55,6 +54,7 @@ use function FriendsOfHyperf\Sentry\startTransaction; use function FriendsOfHyperf\Sentry\trace; +use function Hyperf\Coroutine\defer; use function Sentry\continueTrace; /** @@ -328,7 +328,7 @@ protected function handleRequestReceived(HttpEvent\RequestReceived|RpcEvent\Requ SentrySdk::getCurrentHub()->setSpan($span); - Co::defer(function () use ($transaction, $span) { + defer(function () use ($transaction, $span) { // Make sure the span is finished after the request is handled $span->finish(); @@ -531,7 +531,7 @@ protected function handleCrontabTaskStarting(CrontabEvent\BeforeExecute $event): ]) ); - Co::defer(function () use ($transaction) { + defer(function () use ($transaction) { // Make sure the transaction is finished after the task is executed SentrySdk::getCurrentHub()->setSpan($transaction); @@ -600,7 +600,7 @@ protected function handleAmqpMessageProcessing(AmqpEvent\BeforeConsume $event): ]) ); - Co::defer(function () use ($transaction) { + defer(function () use ($transaction) { // Make sure the transaction is finished after the message is processed SentrySdk::getCurrentHub()->setSpan($transaction); @@ -668,7 +668,7 @@ protected function handleKafkaMessageProcessing(KafkaEvent\BeforeConsume $event) ]) ); - Co::defer(function () use ($transaction) { + defer(function () use ($transaction) { // Make sure the transaction is finished after the message is processed SentrySdk::getCurrentHub()->setSpan($transaction); @@ -718,7 +718,7 @@ protected function handleAsyncQueueJobProcessing(AsyncQueueEvent\BeforeHandle $e ]) ); - Co::defer(function () use ($transaction) { + defer(function () use ($transaction) { // Make sure the transaction is finished after the job is processed SentrySdk::getCurrentHub()->setSpan($transaction); diff --git a/src/sentry/src/Tracing/Tracer.php b/src/sentry/src/Tracing/Tracer.php index 0c9a3e885..77a6a546f 100644 --- a/src/sentry/src/Tracing/Tracer.php +++ b/src/sentry/src/Tracing/Tracer.php @@ -21,6 +21,7 @@ use Sentry\Tracing\TransactionSource; use Throwable; +use function Hyperf\Coroutine\defer; use function Sentry\trace; class Tracer @@ -34,7 +35,7 @@ public function startTransaction(TransactionContext $transactionContext, array $ $hub->pushScope(); $hub->configureScope(static fn (Scope $scope) => $scope->clearBreadcrumbs()); - Co::defer(static fn () => $hub->popScope()); + defer(static fn () => $hub->popScope()); $transactionContext->setData(['coroutine.id' => Co::id()] + $transactionContext->getData()); From 1423d0c87cdb0c357f4872b984a3404e0da70f46 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 22 Dec 2025 11:37:44 +0800 Subject: [PATCH 3/4] fix(sentry): correct condition check for argument existence in SingletonAspect --- src/sentry/src/Aspect/SingletonAspect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Aspect/SingletonAspect.php b/src/sentry/src/Aspect/SingletonAspect.php index 1805944ae..7c3d74191 100644 --- a/src/sentry/src/Aspect/SingletonAspect.php +++ b/src/sentry/src/Aspect/SingletonAspect.php @@ -37,7 +37,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $key = $className = $proceedingJoinPoint->className; $arguments = $proceedingJoinPoint->getArguments(); - if (! empty($arguments)) { + if (! array_key_exists(0, $arguments)) { $key .= '#' . $arguments[0]; } From 384465b4cbfbbd619a94a074a0bf4833d02faa57 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 22 Dec 2025 11:39:51 +0800 Subject: [PATCH 4/4] refactor(sentry): clean up SingletonAspect by commenting out unused singleton classes and enums --- src/sentry/src/Aspect/SingletonAspect.php | 36 ++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/sentry/src/Aspect/SingletonAspect.php b/src/sentry/src/Aspect/SingletonAspect.php index 7c3d74191..089e2a86c 100644 --- a/src/sentry/src/Aspect/SingletonAspect.php +++ b/src/sentry/src/Aspect/SingletonAspect.php @@ -19,17 +19,19 @@ class SingletonAspect extends AbstractAspect { public array $classes = [ - \Sentry\CheckInStatus::class . '::getInstance', - \Sentry\EventType::class . '::getInstance', - \Sentry\MonitorScheduleUnit::class . '::getInstance', + // Singleton Classes + \Sentry\State\HubAdapter::class . '::getInstance', \Sentry\Integration\IntegrationRegistry::class . '::getInstance', - \Sentry\Logs\LogLevel::class . '::getInstance', \Sentry\Metrics\TraceMetrics::class . '::getInstance', - \Sentry\State\HubAdapter::class . '::getInstance', - \Sentry\Tracing\SpanStatus::class . '::getInstance', - \Sentry\Tracing\TransactionSource::class . '::getInstance', - \Sentry\Transport\ResultStatus::class . '::getInstance', - \Sentry\Unit::class . '::getInstance', + // Enums + // \Sentry\CheckInStatus::class . '::getInstance', + // \Sentry\EventType::class . '::getInstance', + // \Sentry\MonitorScheduleUnit::class . '::getInstance', + // \Sentry\Logs\LogLevel::class . '::getInstance', + // \Sentry\Tracing\SpanStatus::class . '::getInstance', + // \Sentry\Tracing\TransactionSource::class . '::getInstance', + // \Sentry\Transport\ResultStatus::class . '::getInstance', + // \Sentry\Unit::class . '::getInstance', ]; public function process(ProceedingJoinPoint $proceedingJoinPoint) @@ -52,14 +54,14 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) }), // Enums - \Sentry\CheckInStatus::class, - \Sentry\EventType::class, - \Sentry\MonitorScheduleUnit::class, - \Sentry\Logs\LogLevel::class, - \Sentry\Tracing\SpanStatus::class, - \Sentry\Tracing\TransactionSource::class, - \Sentry\Transport\ResultStatus::class, - \Sentry\Unit::class => $proceedingJoinPoint->process(), + // \Sentry\CheckInStatus::class, + // \Sentry\EventType::class, + // \Sentry\MonitorScheduleUnit::class, + // \Sentry\Logs\LogLevel::class, + // \Sentry\Tracing\SpanStatus::class, + // \Sentry\Tracing\TransactionSource::class, + // \Sentry\Transport\ResultStatus::class, + // \Sentry\Unit::class => $proceedingJoinPoint->process(), default => $proceedingJoinPoint->process(), }; }