From 90bde500e2f3dece96a46f9098e4c98231646849 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 09:32:32 +0800 Subject: [PATCH 01/32] feat(sentry): support nested spans for console commands This change enables console commands to create child spans when executed within an existing trace, rather than always creating a new transaction. Key improvements: - Check for existing span before creating transaction - Create child span if parent span exists - Properly restore parent span context after command execution - Unified span terminology (replaced transaction-specific references) This provides better trace continuity when commands are executed as part of a larger trace context, while maintaining backward compatibility for standalone command execution. --- .../Tracing/Listener/EventHandleListener.php | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 736456f8b..fb5c071f5 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -375,40 +375,60 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void } $command = $event->getCommand(); + $currentSpan = SentrySdk::getCurrentHub()->getSpan(); + + if ($currentSpan === null) { + $span = startTransaction( + TransactionContext::make() + ->setName($command->getName() ?: '') + ->setOp('console.command') + ->setDescription($command->getDescription()) + ->setOrigin('auto.console') + ->setData([ + 'command.arguments' => (fn () => $this->input->getArguments())->call($command), + 'command.options' => (fn () => $this->input->getOptions())->call($command), + ]) + ->setTags([ + 'command.name' => $command->getName(), + ]) + ->setSource(TransactionSource::task()) + ); + } else { + $span = $currentSpan->startChild( + SpanContext::make() + ->setOp('console.command') + ->setDescription($command->getName() ?: $command->getDescription()) + ->setData([ + 'command.arguments' => (fn () => $this->input->getArguments())->call($command), + 'command.options' => (fn () => $this->input->getOptions())->call($command), + ]) + ->setTags([ + 'command.name' => $command->getName(), + ]) + ); - $transaction = startTransaction( - TransactionContext::make() - ->setName($command->getName() ?: '') - ->setOp('console.command') - ->setDescription($command->getDescription()) - ->setOrigin('auto.console') - ->setData([ - 'command.arguments' => (fn () => $this->input->getArguments())->call($command), - 'command.options' => (fn () => $this->input->getOptions())->call($command), - ]) - ->setTags([ - 'command.name' => $command->getName(), - ]) - ->setSource(TransactionSource::task()) - ); + SentrySdk::getCurrentHub()->setSpan($span); + } - Coroutine::inCoroutine() && defer(function () use ($transaction) { + Coroutine::inCoroutine() && defer(function () use ($span, $currentSpan) { // Make sure the transaction is finished after the command is executed - SentrySdk::getCurrentHub()->setSpan($transaction); + SentrySdk::getCurrentHub()->setSpan($span); // Finish transaction - $transaction->finish(); + $span->finish(); // Flush events Integration::flushEvents(); + + isset($currentSpan) && SentrySdk::getCurrentHub()->setSpan($currentSpan); }); } protected function handleCommandFinished(CommandEvent\AfterExecute $event): void { - $transaction = SentrySdk::getCurrentHub()->getTransaction(); + $span = SentrySdk::getCurrentHub()->getSpan(); - if (! $transaction?->getSampled()) { + if (! $span?->getSampled()) { return; } @@ -417,20 +437,20 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void /** @var int $exitCode */ $exitCode = (fn () => $this->exitCode ?? SymfonyCommand::SUCCESS)->call($command); - $transaction->setTags([ + $span->setTags([ 'command.exit_code' => (string) $exitCode, ]); - $transaction->setStatus( + $span->setStatus( $event->getThrowable() || $exitCode !== SymfonyCommand::SUCCESS ? SpanStatus::internalError() : SpanStatus::ok() ); } finally { if (! Coroutine::inCoroutine()) { - SentrySdk::getCurrentHub()->setSpan($transaction); + SentrySdk::getCurrentHub()->setSpan($span); - $transaction->finish(); + $span->finish(); } } } From 034ad9318350fd8d5a6604fd1cb901b48fe8b5fc Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 09:54:57 +0800 Subject: [PATCH 02/32] fix(sentry): improve scope management for console command spans --- .../Tracing/Listener/EventHandleListener.php | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index fb5c071f5..0e25efdea 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -394,6 +394,7 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ->setSource(TransactionSource::task()) ); } else { + $scope = SentrySdk::getCurrentHub()->pushScope(); $span = $currentSpan->startChild( SpanContext::make() ->setOp('console.command') @@ -406,22 +407,8 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void 'command.name' => $command->getName(), ]) ); - - SentrySdk::getCurrentHub()->setSpan($span); + $scope->setSpan($span); } - - Coroutine::inCoroutine() && defer(function () use ($span, $currentSpan) { - // Make sure the transaction is finished after the command is executed - SentrySdk::getCurrentHub()->setSpan($span); - - // Finish transaction - $span->finish(); - - // Flush events - Integration::flushEvents(); - - isset($currentSpan) && SentrySdk::getCurrentHub()->setSpan($currentSpan); - }); } protected function handleCommandFinished(CommandEvent\AfterExecute $event): void @@ -447,11 +434,13 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void : SpanStatus::ok() ); } finally { - if (! Coroutine::inCoroutine()) { - SentrySdk::getCurrentHub()->setSpan($span); + SentrySdk::getCurrentHub()->setSpan($span); - $span->finish(); - } + $span->finish(); + + Integration::flushEvents(); + + SentrySdk::getCurrentHub()->popScope(); } } From e45ec6a9994e820b9332d8657de6ff2635352039 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:21:49 +0800 Subject: [PATCH 03/32] fix(sentry): update coroutine tracing to use spans instead of transactions --- .../src/Tracing/Aspect/CoroutineAspect.php | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 3f1f20c80..6cc5b086b 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -57,30 +57,33 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) return $proceedingJoinPoint->process(); } - // Get the current transaction from the current scope. - $transaction = SentrySdk::getCurrentHub()->getTransaction(); + // Get the current span from the current scope. + $parentSpan = SentrySdk::getCurrentHub()->getSpan(); - // If there's no active transaction, skip tracing. - if (! $transaction?->getSampled()) { + // If there's no active span, skip tracing. + if (! $parentSpan?->getSampled()) { return $proceedingJoinPoint->process(); } + // Create a new scope for the coroutine. + $scope = SentrySdk::getCurrentHub()->pushScope(); + // Start a span for the coroutine creation. - $parent = $transaction->startChild( + $span = $parentSpan->startChild( SpanContext::make() ->setOp('coroutine.create') ->setDescription($callingOnFunction) ->setOrigin('auto.coroutine') ->setData(['coroutine.id' => Co::id()]) ); - SentrySdk::getCurrentHub()->setSpan($parent); + $scope->setSpan($span); $cid = Co::id(); $keys = $this->keys; $callable = $proceedingJoinPoint->arguments['keys']['callable']; // Transfer the Sentry context to the new coroutine. - $proceedingJoinPoint->arguments['keys']['callable'] = function () use ($callable, $parent, $callingOnFunction, $cid, $keys) { + $proceedingJoinPoint->arguments['keys']['callable'] = function () use ($callable, $span, $callingOnFunction, $cid, $keys) { $from = Co::getContextFor($cid); $current = Co::getContextFor(); @@ -91,7 +94,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) } $coTransaction = startTransaction( - continueTrace($parent->toTraceparent(), $parent->toBaggage()) + continueTrace($span->toTraceparent(), $span->toBaggage()) ->setName('coroutine') ->setOp('coroutine.execute') ->setDescription($callingOnFunction) @@ -121,7 +124,8 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) try { return $proceedingJoinPoint->process(); } finally { - $parent->finish(); + $span->finish(); + SentrySdk::getCurrentHub()->popScope(); } } } From baadab27350c38daa2e342225f06cddf867df5d0 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:29:13 +0800 Subject: [PATCH 04/32] fix(sentry): update span handling in CoroutineAspect and EventHandleListener for improved tracing --- src/sentry/src/Tracing/Aspect/CoroutineAspect.php | 1 + .../src/Tracing/Listener/EventHandleListener.php | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 6cc5b086b..15aeaaa92 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -125,6 +125,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) return $proceedingJoinPoint->process(); } finally { $span->finish(); + SentrySdk::getCurrentHub()->setSpan($parentSpan); SentrySdk::getCurrentHub()->popScope(); } } diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 0e25efdea..f04915715 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -375,9 +375,9 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void } $command = $event->getCommand(); - $currentSpan = SentrySdk::getCurrentHub()->getSpan(); + $parentSpan = SentrySdk::getCurrentHub()->getSpan(); - if ($currentSpan === null) { + if ($parentSpan === null) { $span = startTransaction( TransactionContext::make() ->setName($command->getName() ?: '') @@ -395,7 +395,7 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ); } else { $scope = SentrySdk::getCurrentHub()->pushScope(); - $span = $currentSpan->startChild( + $span = $parentSpan->startChild( SpanContext::make() ->setOp('console.command') ->setDescription($command->getName() ?: $command->getDescription()) @@ -434,12 +434,12 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void : SpanStatus::ok() ); } finally { - SentrySdk::getCurrentHub()->setSpan($span); - $span->finish(); Integration::flushEvents(); + // SentrySdk::getCurrentHub()->setSpan($parentSpan); + SentrySdk::getCurrentHub()->popScope(); } } From 74560b7b201c8d4217537ad1feb71e5766e9f6e9 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:31:28 +0800 Subject: [PATCH 05/32] fix(sentry): refactor span handling in CoroutineAspect for improved clarity and consistency --- .../src/Tracing/Aspect/CoroutineAspect.php | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 15aeaaa92..4f31dc2f7 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -69,14 +69,15 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $scope = SentrySdk::getCurrentHub()->pushScope(); // Start a span for the coroutine creation. - $span = $parentSpan->startChild( - SpanContext::make() - ->setOp('coroutine.create') - ->setDescription($callingOnFunction) - ->setOrigin('auto.coroutine') - ->setData(['coroutine.id' => Co::id()]) + $scope->setSpan( + $span = $parentSpan->startChild( + SpanContext::make() + ->setOp('coroutine.create') + ->setDescription($callingOnFunction) + ->setOrigin('auto.coroutine') + ->setData(['coroutine.id' => Co::id()]) + ) ); - $scope->setSpan($span); $cid = Co::id(); $keys = $this->keys; @@ -93,7 +94,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) } } - $coTransaction = startTransaction( + $transaction = startTransaction( continueTrace($span->toTraceparent(), $span->toBaggage()) ->setName('coroutine') ->setOp('coroutine.execute') @@ -101,12 +102,9 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) ->setOrigin('auto.coroutine') ); - defer(function () use ($coTransaction) { - // Set the transaction on the current scope to ensure it's the active one. - SentrySdk::getCurrentHub()->setSpan($coTransaction); - + defer(function () use ($transaction) { // Finish the transaction when the coroutine ends. - $coTransaction->finish(); + $transaction->finish(); // Flush events Integration::flushEvents(); @@ -115,7 +113,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) try { $callable(); } catch (Throwable $exception) { - $coTransaction->setStatus(SpanStatus::internalError()); + $transaction->setStatus(SpanStatus::internalError()); throw $exception; } From c22cac4bf06e41b89f123fa833504edc9a8a56a4 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 10:32:42 +0800 Subject: [PATCH 06/32] fix(sentry): clarify purpose of commented span handling in EventHandleListener --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index f04915715..f873c74a6 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -438,7 +438,7 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void Integration::flushEvents(); - // SentrySdk::getCurrentHub()->setSpan($parentSpan); + // SentrySdk::getCurrentHub()->setSpan($parentSpan); // Needed? SentrySdk::getCurrentHub()->popScope(); } From 640302715c0562d1764e0fabb7ab488d49fbe458 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:04:01 +0800 Subject: [PATCH 07/32] feat(sentry): add CoContainer for managing Sentry context in a weak reference container --- .../Tracing/Listener/EventHandleListener.php | 11 +++- src/sentry/src/Util/CoContainer.php | 50 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/sentry/src/Util/CoContainer.php diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index f873c74a6..d7a6051d6 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -16,6 +16,7 @@ use FriendsOfHyperf\Sentry\Feature; use FriendsOfHyperf\Sentry\Integration; use FriendsOfHyperf\Sentry\Util\Carrier; +use FriendsOfHyperf\Sentry\Util\CoContainer; use FriendsOfHyperf\Sentry\Util\SqlParser; use FriendsOfHyperf\Support\RedisCommand; use Hyperf\Amqp\Event as AmqpEvent; @@ -43,6 +44,7 @@ use Psr\Container\ContainerInterface; use Sentry\SentrySdk; use Sentry\State\Scope; +use Sentry\Tracing\Span; use Sentry\Tracing\SpanContext; use Sentry\Tracing\SpanStatus; use Sentry\Tracing\TransactionContext; @@ -408,6 +410,7 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ]) ); $scope->setSpan($span); + CoContainer::set($command, $parentSpan); } } @@ -419,8 +422,9 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void return; } + $command = $event->getCommand(); + try { - $command = $event->getCommand(); /** @var int $exitCode */ $exitCode = (fn () => $this->exitCode ?? SymfonyCommand::SUCCESS)->call($command); @@ -438,7 +442,10 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void Integration::flushEvents(); - // SentrySdk::getCurrentHub()->setSpan($parentSpan); // Needed? + $parentSpan = CoContainer::get($command); + if ($parentSpan !== null && $parentSpan instanceof Span) { + SentrySdk::getCurrentHub()->setSpan($parentSpan); + } SentrySdk::getCurrentHub()->popScope(); } diff --git a/src/sentry/src/Util/CoContainer.php b/src/sentry/src/Util/CoContainer.php new file mode 100644 index 000000000..384bec838 --- /dev/null +++ b/src/sentry/src/Util/CoContainer.php @@ -0,0 +1,50 @@ + new WeakMap()); + } +} From 9e296b29292bf7e1c75872dbeac4d898537d0335 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:34:12 +0800 Subject: [PATCH 08/32] fix(sentry): refactor CoContainer method to improve span retrieval logic --- .../src/Tracing/Listener/EventHandleListener.php | 4 ++-- src/sentry/src/Util/CoContainer.php | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index d7a6051d6..7480f872b 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -442,8 +442,8 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void Integration::flushEvents(); - $parentSpan = CoContainer::get($command); - if ($parentSpan !== null && $parentSpan instanceof Span) { + $parentSpan = CoContainer::pull($command); + if ($parentSpan instanceof Span) { SentrySdk::getCurrentHub()->setSpan($parentSpan); } diff --git a/src/sentry/src/Util/CoContainer.php b/src/sentry/src/Util/CoContainer.php index 384bec838..f2fba7dac 100644 --- a/src/sentry/src/Util/CoContainer.php +++ b/src/sentry/src/Util/CoContainer.php @@ -26,9 +26,18 @@ class CoContainer * @param TKey $key * @return null|TValue */ - public static function get(?object $key = null): ?object + public static function pull(?object $key = null): ?object { - return self::getContainer()[$key] ?? null; + $container = self::getContainer(); + + if (! isset($container[$key])) { + return null; + } + + $value = $container[$key]; + unset($container[$key]); + + return $value; } /** From 4d38552a12f5103f6701b6a5c5c0b8a6c54edc5d Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:35:38 +0800 Subject: [PATCH 09/32] fix(sentry): refactor CoContainer methods for improved clarity and organization --- src/sentry/src/Util/CoContainer.php | 35 +++++++++++++++++++---------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/sentry/src/Util/CoContainer.php b/src/sentry/src/Util/CoContainer.php index f2fba7dac..8347f99db 100644 --- a/src/sentry/src/Util/CoContainer.php +++ b/src/sentry/src/Util/CoContainer.php @@ -22,6 +22,29 @@ class CoContainer { public const CONTEXT_KEY = 'sentry.context.container'; + /** + * @param TKey $key + * @param TValue $value + * @return TValue + */ + public static function set(object $key, object $value): object + { + self::getContainer()[$key] = $value; + + return $value; + } + + /** + * @param TKey $key + * @return null|TValue + */ + public static function get(object $key): ?object + { + $container = self::getContainer(); + + return $container[$key] ?? null; + } + /** * @param TKey $key * @return null|TValue @@ -40,18 +63,6 @@ public static function pull(?object $key = null): ?object return $value; } - /** - * @param TKey $key - * @param TValue $value - * @return TValue - */ - public static function set(object $key, object $value): object - { - self::getContainer()[$key] = $value; - - return $value; - } - private static function getContainer(): WeakMap { return Context::get(self::CONTEXT_KEY, fn () => new WeakMap()); From a8228356288b27839dcc1f1a68742129245a6acd Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:38:44 +0800 Subject: [PATCH 10/32] fix(sentry): add sampling check for parent span in EventHandleListener --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 7480f872b..6866b5549 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -396,6 +396,10 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ->setSource(TransactionSource::task()) ); } else { + if (! $parentSpan->getSampled()) { + return; + } + $scope = SentrySdk::getCurrentHub()->pushScope(); $span = $parentSpan->startChild( SpanContext::make() @@ -410,6 +414,7 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ]) ); $scope->setSpan($span); + CoContainer::set($command, $parentSpan); } } From bd15825c8afe1b7c2f711aab6fe2532f47c64c90 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:41:34 +0800 Subject: [PATCH 11/32] fix(sentry): add del method to CoContainer for removing items from the container --- src/sentry/src/Util/CoContainer.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sentry/src/Util/CoContainer.php b/src/sentry/src/Util/CoContainer.php index 8347f99db..eaf2854c1 100644 --- a/src/sentry/src/Util/CoContainer.php +++ b/src/sentry/src/Util/CoContainer.php @@ -63,6 +63,11 @@ public static function pull(?object $key = null): ?object return $value; } + public static function del(object $key): void + { + unset(self::getContainer()[$key]); + } + private static function getContainer(): WeakMap { return Context::get(self::CONTEXT_KEY, fn () => new WeakMap()); From 472d6b32be88130b51c7ea1f3da88acad51743d3 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 11:44:00 +0800 Subject: [PATCH 12/32] fix(sentry): update getContainer method to use getOrSet for better context management --- src/sentry/src/Util/CoContainer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Util/CoContainer.php b/src/sentry/src/Util/CoContainer.php index eaf2854c1..7b5523738 100644 --- a/src/sentry/src/Util/CoContainer.php +++ b/src/sentry/src/Util/CoContainer.php @@ -70,6 +70,6 @@ public static function del(object $key): void private static function getContainer(): WeakMap { - return Context::get(self::CONTEXT_KEY, fn () => new WeakMap()); + return Context::getOrSet(self::CONTEXT_KEY, fn () => new WeakMap()); } } From 2d621305122199f38fecf82e3c40567110b95623 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 12:30:39 +0800 Subject: [PATCH 13/32] fix(sentry): refactor coroutine execution to use trace function for better span management --- .../src/Tracing/Aspect/CoroutineAspect.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 4f31dc2f7..d78160f15 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -19,10 +19,9 @@ use Hyperf\Engine\Coroutine as Co; use Sentry\SentrySdk; use Sentry\Tracing\SpanContext; -use Sentry\Tracing\SpanStatus; -use Throwable; use function FriendsOfHyperf\Sentry\startTransaction; +use function FriendsOfHyperf\Sentry\trace; use function Hyperf\Coroutine\defer; use function Sentry\continueTrace; @@ -110,13 +109,13 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) Integration::flushEvents(); }); - try { - $callable(); - } catch (Throwable $exception) { - $transaction->setStatus(SpanStatus::internalError()); - - throw $exception; - } + return trace( + $callable, + SpanContext::make() + ->setOp('coroutine.run') + ->setDescription($callingOnFunction) + ->setOrigin('auto.coroutine') + ); }; try { From de65019519ef0396ddbeb9c73b7bcf89516b7148 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 13:05:35 +0800 Subject: [PATCH 14/32] fix(sentry): adjust scope management in EventHandleListener for improved span handling --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 6866b5549..de437b545 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -450,9 +450,8 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void $parentSpan = CoContainer::pull($command); if ($parentSpan instanceof Span) { SentrySdk::getCurrentHub()->setSpan($parentSpan); + SentrySdk::getCurrentHub()->popScope(); } - - SentrySdk::getCurrentHub()->popScope(); } } From 29df54bbeb6baf6c179777d1141fa1ebeebf2398 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 13:45:53 +0800 Subject: [PATCH 15/32] fix(sentry): ensure parent span is restored after coroutine processing --- src/sentry/src/Tracing/Aspect/CoroutineAspect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index d78160f15..c2e1ea671 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -122,8 +122,8 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) return $proceedingJoinPoint->process(); } finally { $span->finish(); - SentrySdk::getCurrentHub()->setSpan($parentSpan); SentrySdk::getCurrentHub()->popScope(); + SentrySdk::getCurrentHub()->setSpan($parentSpan); } } } From a1219a0150c0565f465f8f6e117781f06cadef70 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 14:06:13 +0800 Subject: [PATCH 16/32] fix(sentry): streamline coroutine span creation by removing unnecessary scope management --- .../src/Tracing/Aspect/CoroutineAspect.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index c2e1ea671..d9d0bc5fe 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -64,18 +64,13 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) return $proceedingJoinPoint->process(); } - // Create a new scope for the coroutine. - $scope = SentrySdk::getCurrentHub()->pushScope(); - // Start a span for the coroutine creation. - $scope->setSpan( - $span = $parentSpan->startChild( - SpanContext::make() - ->setOp('coroutine.create') - ->setDescription($callingOnFunction) - ->setOrigin('auto.coroutine') - ->setData(['coroutine.id' => Co::id()]) - ) + $span = $parentSpan->startChild( + SpanContext::make() + ->setOp('coroutine.create') + ->setDescription($callingOnFunction) + ->setOrigin('auto.coroutine') + ->setData(['coroutine.id' => Co::id()]) ); $cid = Co::id(); @@ -122,7 +117,6 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) return $proceedingJoinPoint->process(); } finally { $span->finish(); - SentrySdk::getCurrentHub()->popScope(); SentrySdk::getCurrentHub()->setSpan($parentSpan); } } From 61664529e09291c79c5ceb311bdd494ad27bcbf3 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 14:15:12 +0800 Subject: [PATCH 17/32] fix(sentry): refactor callable in trace function to use static closure for coroutine execution --- src/sentry/src/Tracing/Aspect/CoroutineAspect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index d9d0bc5fe..41fe4c953 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -105,7 +105,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) }); return trace( - $callable, + static fn () => $callable(), SpanContext::make() ->setOp('coroutine.run') ->setDescription($callingOnFunction) From 390a5f9057d9f6084776c6eb5ca357ef030266cf Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 14:18:52 +0800 Subject: [PATCH 18/32] fix(CoContainer): update pull method to require a non-null object key --- src/sentry/src/Util/CoContainer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Util/CoContainer.php b/src/sentry/src/Util/CoContainer.php index 7b5523738..1cd27a36a 100644 --- a/src/sentry/src/Util/CoContainer.php +++ b/src/sentry/src/Util/CoContainer.php @@ -49,7 +49,7 @@ public static function get(object $key): ?object * @param TKey $key * @return null|TValue */ - public static function pull(?object $key = null): ?object + public static function pull(object $key): ?object { $container = self::getContainer(); From 27e19c2376f18fa83065610b324fac8da5eb8790 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 14:20:21 +0800 Subject: [PATCH 19/32] fix(EventHandleListener): streamline span tag and status setting for improved readability --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index de437b545..7b098023b 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -435,12 +435,10 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void $span->setTags([ 'command.exit_code' => (string) $exitCode, - ]); - - $span->setStatus( + ])->setStatus( $event->getThrowable() || $exitCode !== SymfonyCommand::SUCCESS - ? SpanStatus::internalError() - : SpanStatus::ok() + ? SpanStatus::internalError() + : SpanStatus::ok() ); } finally { $span->finish(); From 9c1fbff081357894661b9f09a77d6c223e8c1907 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 14:21:29 +0800 Subject: [PATCH 20/32] fix(EventHandleListener): remove unnecessary parent span sampling check for streamlined processing --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 7b098023b..548cb0879 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -396,10 +396,6 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ->setSource(TransactionSource::task()) ); } else { - if (! $parentSpan->getSampled()) { - return; - } - $scope = SentrySdk::getCurrentHub()->pushScope(); $span = $parentSpan->startChild( SpanContext::make() From f4c047086ba59ea779a8002b0deec3b59637fc25 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:16:15 +0800 Subject: [PATCH 21/32] fix(CoroutineAspect): initialize Sentry SDK before transferring context to new coroutine --- src/sentry/src/Tracing/Aspect/CoroutineAspect.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 41fe4c953..5a0b52552 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -79,6 +79,8 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) // Transfer the Sentry context to the new coroutine. $proceedingJoinPoint->arguments['keys']['callable'] = function () use ($callable, $span, $callingOnFunction, $cid, $keys) { + SentrySdk::init(); + $from = Co::getContextFor($cid); $current = Co::getContextFor(); From c0cda260dc12e4622c59850cb6da6015f5e7e93f Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:23:47 +0800 Subject: [PATCH 22/32] fix(CoroutineAspect): ensure Sentry SDK initialization in new coroutine context transfer --- .../src/Tracing/Aspect/CoroutineAspect.php | 111 ++++++++---------- 1 file changed, 46 insertions(+), 65 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 5a0b52552..58ab4b4e3 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -18,6 +18,7 @@ use Hyperf\Di\Aop\ProceedingJoinPoint; use Hyperf\Engine\Coroutine as Co; use Sentry\SentrySdk; +use Sentry\State\Scope; use Sentry\Tracing\SpanContext; use function FriendsOfHyperf\Sentry\startTransaction; @@ -51,75 +52,55 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $callingOnFunction = CoroutineBacktraceHelper::foundCallingOnFunction(); - // Only trace the top-level coroutine creation. - if (! $callingOnFunction) { - return $proceedingJoinPoint->process(); - } - - // Get the current span from the current scope. - $parentSpan = SentrySdk::getCurrentHub()->getSpan(); - - // If there's no active span, skip tracing. - if (! $parentSpan?->getSampled()) { - return $proceedingJoinPoint->process(); - } + return trace( + function (Scope $scope) use ($proceedingJoinPoint, $callingOnFunction) { + if ($callingOnFunction && $span = $scope->getSpan()) { + $cid = Co::id(); + $keys = $this->keys; + $callable = $proceedingJoinPoint->arguments['keys']['callable']; + + // Transfer the Sentry context to the new coroutine. + $proceedingJoinPoint->arguments['keys']['callable'] = function () use ($callable, $span, $callingOnFunction, $cid, $keys) { + SentrySdk::init(); // Ensure Sentry is initialized in the new coroutine. + + $from = Co::getContextFor($cid); + $current = Co::getContextFor(); + + foreach ($keys as $key) { + if (isset($from[$key]) && ! isset($current[$key])) { + $current[$key] = $from[$key]; + } + } + + $transaction = startTransaction( + continueTrace($span->toTraceparent(), $span->toBaggage()) + ->setName('coroutine') + ->setOp('coroutine.execute') + ->setDescription($callingOnFunction) + ->setOrigin('auto.coroutine') + ); + + defer(function () use ($transaction) { + $transaction->finish(); + Integration::flushEvents(); + }); + + return trace( + fn () => $callable(), + SpanContext::make() + ->setOp('coroutine.run') + ->setDescription($callingOnFunction) + ->setOrigin('auto.coroutine') + ); + }; + } - // Start a span for the coroutine creation. - $span = $parentSpan->startChild( + return $proceedingJoinPoint->process(); + }, SpanContext::make() - ->setOp('coroutine.create') + ->setOp('coroutine.aspect') ->setDescription($callingOnFunction) ->setOrigin('auto.coroutine') - ->setData(['coroutine.id' => Co::id()]) ); - - $cid = Co::id(); - $keys = $this->keys; - $callable = $proceedingJoinPoint->arguments['keys']['callable']; - - // Transfer the Sentry context to the new coroutine. - $proceedingJoinPoint->arguments['keys']['callable'] = function () use ($callable, $span, $callingOnFunction, $cid, $keys) { - SentrySdk::init(); - - $from = Co::getContextFor($cid); - $current = Co::getContextFor(); - - foreach ($keys as $key) { - if (isset($from[$key]) && ! isset($current[$key])) { - $current[$key] = $from[$key]; - } - } - - $transaction = startTransaction( - continueTrace($span->toTraceparent(), $span->toBaggage()) - ->setName('coroutine') - ->setOp('coroutine.execute') - ->setDescription($callingOnFunction) - ->setOrigin('auto.coroutine') - ); - - defer(function () use ($transaction) { - // Finish the transaction when the coroutine ends. - $transaction->finish(); - - // Flush events - Integration::flushEvents(); - }); - - return trace( - static fn () => $callable(), - SpanContext::make() - ->setOp('coroutine.run') - ->setDescription($callingOnFunction) - ->setOrigin('auto.coroutine') - ); - }; - - try { - return $proceedingJoinPoint->process(); - } finally { - $span->finish(); - SentrySdk::getCurrentHub()->setSpan($parentSpan); - } } } From 714eb36ed34f1d4efb467029b9c33ba7615495b0 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:24:23 +0800 Subject: [PATCH 23/32] fix(CoroutineAspect): update operation name to 'coroutine.create' for accurate tracing --- src/sentry/src/Tracing/Aspect/CoroutineAspect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 58ab4b4e3..4725625fb 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -98,7 +98,7 @@ function (Scope $scope) use ($proceedingJoinPoint, $callingOnFunction) { return $proceedingJoinPoint->process(); }, SpanContext::make() - ->setOp('coroutine.aspect') + ->setOp('coroutine.create') ->setDescription($callingOnFunction) ->setOrigin('auto.coroutine') ); From 3c0c510443449db7ff07ba1f64011c4874501fa7 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:28:16 +0800 Subject: [PATCH 24/32] fix(CoroutineAspect): update operation names for better tracing accuracy --- src/sentry/src/Tracing/Aspect/CoroutineAspect.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 4725625fb..6f91429a5 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -75,7 +75,7 @@ function (Scope $scope) use ($proceedingJoinPoint, $callingOnFunction) { $transaction = startTransaction( continueTrace($span->toTraceparent(), $span->toBaggage()) ->setName('coroutine') - ->setOp('coroutine.execute') + ->setOp('coroutine.prepare') ->setDescription($callingOnFunction) ->setOrigin('auto.coroutine') ); @@ -88,7 +88,7 @@ function (Scope $scope) use ($proceedingJoinPoint, $callingOnFunction) { return trace( fn () => $callable(), SpanContext::make() - ->setOp('coroutine.run') + ->setOp('coroutine.execute') ->setDescription($callingOnFunction) ->setOrigin('auto.coroutine') ); From 1fc371837b5d4c5a34ef0f914a79fb7e226cfecf Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:33:18 +0800 Subject: [PATCH 25/32] fix(EventHandleListener): streamline span handling by consolidating parent span checks --- .../Tracing/Listener/EventHandleListener.php | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 548cb0879..5cf608e93 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -377,10 +377,9 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void } $command = $event->getCommand(); - $parentSpan = SentrySdk::getCurrentHub()->getSpan(); - if ($parentSpan === null) { - $span = startTransaction( + if (! $parentSpan = SentrySdk::getCurrentHub()->getSpan()) { + $parentSpan = startTransaction( TransactionContext::make() ->setName($command->getName() ?: '') ->setOp('console.command') @@ -395,24 +394,24 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ]) ->setSource(TransactionSource::task()) ); - } else { - $scope = SentrySdk::getCurrentHub()->pushScope(); - $span = $parentSpan->startChild( - SpanContext::make() - ->setOp('console.command') - ->setDescription($command->getName() ?: $command->getDescription()) - ->setData([ - 'command.arguments' => (fn () => $this->input->getArguments())->call($command), - 'command.options' => (fn () => $this->input->getOptions())->call($command), - ]) - ->setTags([ - 'command.name' => $command->getName(), - ]) - ); - $scope->setSpan($span); - - CoContainer::set($command, $parentSpan); } + + $scope = SentrySdk::getCurrentHub()->pushScope(); + $span = $parentSpan->startChild( + SpanContext::make() + ->setOp('console.command') + ->setDescription($command->getName() ?: $command->getDescription()) + ->setData([ + 'command.arguments' => (fn () => $this->input->getArguments())->call($command), + 'command.options' => (fn () => $this->input->getOptions())->call($command), + ]) + ->setTags([ + 'command.name' => $command->getName(), + ]) + ); + $scope->setSpan($span); + + CoContainer::set($command, $parentSpan); } protected function handleCommandFinished(CommandEvent\AfterExecute $event): void @@ -442,6 +441,7 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void Integration::flushEvents(); $parentSpan = CoContainer::pull($command); + if ($parentSpan instanceof Span) { SentrySdk::getCurrentHub()->setSpan($parentSpan); SentrySdk::getCurrentHub()->popScope(); From f91fa266e1e9b6476ade8ebdc297f6da1d15a5ea Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:34:22 +0800 Subject: [PATCH 26/32] fix(EventHandleListener): add check for parent span sampling before proceeding --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 5cf608e93..c809fe687 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -396,6 +396,10 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ); } + if (! $parentSpan->getSampled()) { + return; + } + $scope = SentrySdk::getCurrentHub()->pushScope(); $span = $parentSpan->startChild( SpanContext::make() From 77d78fd32491741350e2ef3d2def3f8c94d2356b Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:45:21 +0800 Subject: [PATCH 27/32] fix(EventHandleListener): ensure proper handling of parent span lifecycle in command execution --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index c809fe687..741f0e1d8 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -394,6 +394,8 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ]) ->setSource(TransactionSource::task()) ); + + CoContainer::set($command, $parentSpan); } if (! $parentSpan->getSampled()) { @@ -414,8 +416,6 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ]) ); $scope->setSpan($span); - - CoContainer::set($command, $parentSpan); } protected function handleCommandFinished(CommandEvent\AfterExecute $event): void @@ -436,8 +436,8 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void 'command.exit_code' => (string) $exitCode, ])->setStatus( $event->getThrowable() || $exitCode !== SymfonyCommand::SUCCESS - ? SpanStatus::internalError() - : SpanStatus::ok() + ? SpanStatus::internalError() + : SpanStatus::ok() ); } finally { $span->finish(); @@ -447,6 +447,7 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void $parentSpan = CoContainer::pull($command); if ($parentSpan instanceof Span) { + $parentSpan->finish(); SentrySdk::getCurrentHub()->setSpan($parentSpan); SentrySdk::getCurrentHub()->popScope(); } From 306fd085f76167622147528d9cc8ac1d7ac4b518 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:49:46 +0800 Subject: [PATCH 28/32] fix(EventHandleListener): update operation name to 'console.command.execute' for accurate command tracing --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 741f0e1d8..22927c7c3 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -405,7 +405,7 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void $scope = SentrySdk::getCurrentHub()->pushScope(); $span = $parentSpan->startChild( SpanContext::make() - ->setOp('console.command') + ->setOp('console.command.execute') ->setDescription($command->getName() ?: $command->getDescription()) ->setData([ 'command.arguments' => (fn () => $this->input->getArguments())->call($command), From f807d7c4f017d22250d06573003bc2dce1a5c98e Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:56:21 +0800 Subject: [PATCH 29/32] fix(EventHandleListener): ensure parent span is set in CoContainer only if sampled --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 22927c7c3..42a4f4110 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -394,14 +394,14 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ]) ->setSource(TransactionSource::task()) ); - - CoContainer::set($command, $parentSpan); } if (! $parentSpan->getSampled()) { return; } + CoContainer::set($command, $parentSpan); + $scope = SentrySdk::getCurrentHub()->pushScope(); $span = $parentSpan->startChild( SpanContext::make() From a8315035e6931592818ceb8d40e6b10f65e1e734 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 16:00:10 +0800 Subject: [PATCH 30/32] fix(EventHandleListener): improve parent span handling by checking span instance and sampling before finishing --- .../src/Tracing/Listener/EventHandleListener.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 42a4f4110..091876339 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -422,13 +422,18 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void { $span = SentrySdk::getCurrentHub()->getSpan(); - if (! $span?->getSampled()) { + if (! $span instanceof Span) { return; } $command = $event->getCommand(); + $sampled = $span->getSampled(); try { + if (! $sampled) { + return; + } + /** @var int $exitCode */ $exitCode = (fn () => $this->exitCode ?? SymfonyCommand::SUCCESS)->call($command); @@ -440,14 +445,14 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void : SpanStatus::ok() ); } finally { - $span->finish(); - - Integration::flushEvents(); + if ($sampled) { + $span->finish(); + Integration::flushEvents(); + } $parentSpan = CoContainer::pull($command); if ($parentSpan instanceof Span) { - $parentSpan->finish(); SentrySdk::getCurrentHub()->setSpan($parentSpan); SentrySdk::getCurrentHub()->popScope(); } From 4614ce27c217c6cfdef0e1a4107427b6c4ecfb1e Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 16:06:24 +0800 Subject: [PATCH 31/32] fix(EventHandleListener): ensure parent span is finished before setting in CoContainer --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index 091876339..f7505af44 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -394,14 +394,14 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void ]) ->setSource(TransactionSource::task()) ); + + CoContainer::set($command, $parentSpan); } if (! $parentSpan->getSampled()) { return; } - CoContainer::set($command, $parentSpan); - $scope = SentrySdk::getCurrentHub()->pushScope(); $span = $parentSpan->startChild( SpanContext::make() @@ -453,6 +453,7 @@ protected function handleCommandFinished(CommandEvent\AfterExecute $event): void $parentSpan = CoContainer::pull($command); if ($parentSpan instanceof Span) { + $parentSpan->finish(); SentrySdk::getCurrentHub()->setSpan($parentSpan); SentrySdk::getCurrentHub()->popScope(); } From 386369aaa0779cfa1a08043e9f63a5332b796916 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Mon, 13 Oct 2025 16:08:07 +0800 Subject: [PATCH 32/32] fix(EventHandleListener): remove command from CoContainer if parent span is not sampled --- src/sentry/src/Tracing/Listener/EventHandleListener.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sentry/src/Tracing/Listener/EventHandleListener.php b/src/sentry/src/Tracing/Listener/EventHandleListener.php index f7505af44..9bc7e3e8a 100644 --- a/src/sentry/src/Tracing/Listener/EventHandleListener.php +++ b/src/sentry/src/Tracing/Listener/EventHandleListener.php @@ -399,6 +399,7 @@ protected function handleCommandStarting(CommandEvent\BeforeHandle $event): void } if (! $parentSpan->getSampled()) { + CoContainer::del($command); return; }