-
-
Notifications
You must be signed in to change notification settings - Fork 27
feat(sentry): add AsyncHttpTransport for non-blocking error reporting #907
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
f370ec0
feat(sentry): add AsyncHttpTransport for non-blocking error reporting
huangdijia 1dbcd62
fix(sentry): prevent memory leak by nullifying event after sending
huangdijia 2dc2881
feat(transport): make channel size configurable in AsyncHttpTransport…
huangdijia f028983
feat(sentry): implement AsyncHttpTransportFactory for creating AsyncH…
huangdijia e762129
fix(transport): refactor close method to avoid code duplication
huangdijia e20ff5a
fix(transport): improve close method to prevent unnecessary null assi…
huangdijia 538da30
fix(transport): refactor close method to call closeChannel instead of…
huangdijia 313f499
fix(transport): throw exception in loop method when worker has exited
huangdijia ce985f1
fix(sentry): log error when sending event to Sentry fails
huangdijia e95c659
fix(transport): add concurrent limit options to AsyncHttpTransport an…
huangdijia b0a9ab9
fix(sentry): uncomment http channel size and concurrent limit options…
huangdijia 01c37e4
fix(transport): add nullsafe operator to channel pop method in AsyncH…
huangdijia c7383bf
refactor(transport): restructure AsyncHttpTransport by moving transpo…
huangdijia 130be04
refactor(transport): replace AsyncHttpTransportFactory with direct in…
huangdijia 286a88d
fix(transport): handle closed transport gracefully and improve logger…
huangdijia 5f3bb34
refactor(transport): rename transport methods for clarity and mark Ht…
huangdijia 8f3200d
feat(sentry): add transport channel size and concurrent limit configu…
huangdijia a71c19f
Remove unused HttpClientInterface references
huangdijia 3d1a2bc
refactor(transport): replace AsyncHttpTransport with CoHttpTransport …
huangdijia 60d6d9c
refactor(factory): mark http_channel_size and http_concurrent_limit a…
huangdijia 6a19aeb
refactor(factory): add comments to clarify transport selection logic
huangdijia b1d1492
refactor(transport): simplify transport initialization and remove unu…
huangdijia 2ac6235
Revert "refactor(transport): simplify transport initialization and re…
huangdijia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
| /** | ||
| * This file is part of friendsofhyperf/components. | ||
| * | ||
| * @link https://github.com/friendsofhyperf/components | ||
| * @document https://github.com/friendsofhyperf/components/blob/main/README.md | ||
| * @contact huangdijia@gmail.com | ||
| */ | ||
|
|
||
| namespace FriendsOfHyperf\Sentry\Transport; | ||
|
|
||
| use Hyperf\Coordinator\Constants; | ||
| use Hyperf\Coordinator\CoordinatorManager; | ||
| use Hyperf\Coroutine\Concurrent; | ||
| use Hyperf\Engine\Channel; | ||
| use Hyperf\Engine\Coroutine; | ||
| use Psr\Container\ContainerInterface; | ||
| use Sentry\ClientBuilder; | ||
| use Sentry\Event; | ||
| use Sentry\Serializer\PayloadSerializer; | ||
| use Sentry\Transport\Result; | ||
| use Sentry\Transport\ResultStatus; | ||
| use Sentry\Transport\TransportInterface; | ||
| use Throwable; | ||
|
|
||
| use function Hyperf\Support\msleep; | ||
|
|
||
| class CoHttpTransport implements TransportInterface | ||
| { | ||
| protected ?Channel $chan = null; | ||
|
|
||
| protected bool $workerExited = false; | ||
|
|
||
| protected ?Coroutine $workerWatcher = null; | ||
|
|
||
| protected ?Concurrent $concurrent = null; | ||
|
|
||
| protected ?ClientBuilder $clientBuilder = null; | ||
|
|
||
| protected int $channelSize = 65535; | ||
|
|
||
| public function __construct( | ||
| protected ContainerInterface $container, | ||
| ) { | ||
| $config = $this->container->get('config'); | ||
| $channelSize = (int) $config->get('sentry.transport_channel_size', 65535); | ||
| if ($channelSize > 0) { | ||
| $this->channelSize = $channelSize; | ||
| } | ||
| $concurrentLimit = (int) $config->get('sentry.transport_concurrent_limit', 1000); | ||
| if ($concurrentLimit > 0) { | ||
| $this->concurrent = new Concurrent($concurrentLimit); | ||
| } | ||
| } | ||
|
|
||
| public function send(Event $event): Result | ||
| { | ||
| $this->loop(); | ||
|
|
||
| $chan = $this->chan; | ||
| $chan?->push($event); | ||
|
|
||
| return new Result(ResultStatus::success(), $event); | ||
| } | ||
|
|
||
| public function close(?int $timeout = null): Result | ||
| { | ||
| return new Result(ResultStatus::success()); | ||
| } | ||
|
|
||
| protected function loop(): void | ||
| { | ||
| if ($this->workerExited) { | ||
| return; | ||
| } | ||
|
|
||
| if ($this->chan !== null) { | ||
| return; | ||
| } | ||
|
|
||
| $this->chan = new Channel($this->channelSize); | ||
|
|
||
| Coroutine::create(function () { | ||
| while (true) { | ||
| $transport = $this->makeHttpTransport(); | ||
| $logger = $this->clientBuilder?->getLogger(); | ||
|
|
||
| while (true) { | ||
| /** @var Event|false|null $event */ | ||
| $event = $this->chan?->pop(); | ||
|
|
||
| if (! $event) { | ||
| break 2; | ||
| } | ||
|
|
||
| try { | ||
| $callable = static fn () => $transport->send($event); | ||
| if ($this->concurrent !== null) { | ||
| $this->concurrent->create($callable); | ||
| } else { | ||
| Coroutine::create($callable); | ||
| } | ||
| } catch (Throwable $e) { | ||
| $logger?->error('Failed to send event to Sentry: ' . $e->getMessage(), ['exception' => $e]); | ||
| $transport->close(); | ||
|
|
||
| break; | ||
| } finally { | ||
| // Prevent memory leak | ||
| $event = null; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| $this->closeChannel(); | ||
| }); | ||
|
|
||
| $this->workerWatcher ??= Coroutine::create(function () { | ||
| if (CoordinatorManager::until(Constants::WORKER_EXIT)->yield()) { | ||
| $this->workerExited = true; | ||
|
|
||
| while (! $this->chan?->isEmpty()) { | ||
| msleep(100); | ||
| } | ||
|
|
||
| $this->closeChannel(); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| protected function makeHttpTransport(): TransportInterface | ||
| { | ||
| $this->clientBuilder ??= $this->container->get(ClientBuilder::class); | ||
|
|
||
| return new \Sentry\Transport\HttpTransport( | ||
| $this->clientBuilder->getOptions(), | ||
| $this->clientBuilder->getHttpClient(), | ||
| new PayloadSerializer($this->clientBuilder->getOptions()), | ||
| $this->clientBuilder->getLogger() | ||
| ); | ||
| } | ||
|
|
||
| protected function closeChannel(): void | ||
| { | ||
| $chan = $this->chan; | ||
| $chan?->close(); | ||
|
|
||
| if ($this->chan === $chan) { | ||
| $this->chan = null; | ||
| } | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.