Skip to content

Commit 6cce8a1

Browse files
committed
feat(sentry): add SentrySdkAspect for coroutine-safe SDK usage
Add an aspect that intercepts SentrySdk::init, ::setCurrentHub, and ::getRuntimeContextManager to make them coroutine-safe using Hyperf's Context API and RuntimeContextManager. This ensures that Sentry SDK works correctly in a coroutine environment by storing the runtime context manager in Hyperf's context storage.
1 parent 15d5ca9 commit 6cce8a1

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of friendsofhyperf/components.
6+
*
7+
* @link https://github.com/friendsofhyperf/components
8+
* @document https://github.com/friendsofhyperf/components/blob/main/README.md
9+
* @contact huangdijia@gmail.com
10+
*/
11+
12+
namespace FriendsOfHyperf\Sentry\Aspect;
13+
14+
use Closure;
15+
use Hyperf\Context\Context;
16+
use Hyperf\Di\Aop\AbstractAspect;
17+
use Hyperf\Di\Aop\ProceedingJoinPoint;
18+
use Sentry\SentrySdk;
19+
use Sentry\State\HubInterface;
20+
use Sentry\State\RuntimeContextManager;
21+
22+
use function Hyperf\Support\make;
23+
24+
class SentrySdkAspect extends AbstractAspect
25+
{
26+
public array $classes = [
27+
SentrySdk::class . '::init',
28+
SentrySdk::class . '::setCurrentHub',
29+
SentrySdk::class . '::getRuntimeContextManager',
30+
];
31+
32+
public function process(ProceedingJoinPoint $proceedingJoinPoint)
33+
{
34+
// Do nothing, just for class mapping.
35+
return match ($proceedingJoinPoint->methodName) {
36+
'init' => $this->handleInit($proceedingJoinPoint),
37+
'setCurrentHub' => $this->handleSetCurrentHub($proceedingJoinPoint),
38+
'getRuntimeContextManager' => $this->handleGetRuntimeContextManager($proceedingJoinPoint),
39+
default => $proceedingJoinPoint->process(),
40+
};
41+
}
42+
43+
private function handleInit(ProceedingJoinPoint $proceedingJoinPoint)
44+
{
45+
Context::set(
46+
RuntimeContextManager::class,
47+
new RuntimeContextManager(make(HubInterface::class))
48+
);
49+
50+
return SentrySdk::getCurrentHub();
51+
}
52+
53+
private function handleSetCurrentHub(ProceedingJoinPoint $proceedingJoinPoint)
54+
{
55+
$arguments = $proceedingJoinPoint->arguments ?? [];
56+
$hub = $arguments['hub'];
57+
// @phpstan-ignore-next-line
58+
Closure::bind(fn () => static::getRuntimeContextManager()->setCurrentHub($hub), null, SentrySdk::class)();
59+
60+
return $hub;
61+
}
62+
63+
private function handleGetRuntimeContextManager(ProceedingJoinPoint $proceedingJoinPoint)
64+
{
65+
return Context::getOrSet(
66+
RuntimeContextManager::class,
67+
fn () => new RuntimeContextManager(make(HubInterface::class))
68+
);
69+
}
70+
}

src/sentry/src/ConfigProvider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public function __invoke(): array
2828
Aspect\LoggerAspect::class,
2929
Aspect\RedisAspect::class,
3030
// Aspect\SingletonAspect::class,
31+
Aspect\SentrySdkAspect::class,
3132
Metrics\Aspect\CounterAspect::class,
3233
Metrics\Aspect\HistogramAspect::class,
3334
Tracing\Aspect\AmqpProducerAspect::class,

0 commit comments

Comments
 (0)