From f370ec0f18be30221fd85318b977bf8292c2c20f Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:21:21 +0800 Subject: [PATCH 01/23] feat(sentry): add AsyncHttpTransport for non-blocking error reporting - Implements asynchronous HTTP transport for Sentry events - Uses Hyperf coroutines and channels for non-blocking operation - Handles graceful shutdown with worker exit coordination - Provides memory-efficient event queuing with 65535 capacity - Maintains compatibility with existing Sentry transport interface --- .../src/Transport/AsyncHttpTransport.php | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/sentry/src/Transport/AsyncHttpTransport.php diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php new file mode 100644 index 000000000..08a0d42e6 --- /dev/null +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -0,0 +1,108 @@ +transport = new \Sentry\Transport\HttpTransport( + $this->clientBuilder->getOptions(), + $this->clientBuilder->getHttpClient(), + new PayloadSerializer($this->clientBuilder->getOptions()), + $this->clientBuilder->getLogger() + ); + } + + 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(65535); + + go(function () { + while (true) { + /** @var Event|false|null $event */ + $event = $this->chan->pop(); + + if (! $event) { + break; + } + + try { + $this->transport->send($event); + } catch (Throwable $e) { + break; + } + } + + $this->chan?->close(); + $this->chan = null; + }); + + $this->workerWatcher ??= Coroutine::create(function () { + if (CoordinatorManager::until(Constants::WORKER_EXIT)->yield()) { + $this->workerExited = true; + + while (! $this->chan?->isEmpty()) { + msleep(100); + } + + $this->chan?->close(); + $this->chan = null; + } + }); + } +} From 1dbcd629e8b08b4bb442707e61d68138f6434b46 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:22:20 +0800 Subject: [PATCH 02/23] fix(sentry): prevent memory leak by nullifying event after sending --- src/sentry/src/Transport/AsyncHttpTransport.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 08a0d42e6..2857bde40 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -70,7 +70,7 @@ protected function loop(): void return; } - $this->chan = new Channel(65535); + $this->chan = new Channel(65535); // TODO: make it configurable go(function () { while (true) { @@ -85,6 +85,9 @@ protected function loop(): void $this->transport->send($event); } catch (Throwable $e) { break; + } finally { + // Prevent memory leak + $event = null; } } From 2dc2881cc5bb3f6eec01a412cdad68961e41207f Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:23:01 +0800 Subject: [PATCH 03/23] feat(transport): make channel size configurable in AsyncHttpTransport constructor --- src/sentry/src/Transport/AsyncHttpTransport.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 2857bde40..0d7cbeca1 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -35,8 +35,10 @@ class AsyncHttpTransport implements TransportInterface protected ?Coroutine $workerWatcher = null; - public function __construct(protected ClientBuilder $clientBuilder) - { + public function __construct( + protected ClientBuilder $clientBuilder, + protected int $channelSize = 65535, + ) { $this->transport = new \Sentry\Transport\HttpTransport( $this->clientBuilder->getOptions(), $this->clientBuilder->getHttpClient(), @@ -70,7 +72,7 @@ protected function loop(): void return; } - $this->chan = new Channel(65535); // TODO: make it configurable + $this->chan = new Channel($this->channelSize); go(function () { while (true) { From f0289835514181a95d26f36290351a5025cdf49b Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:29:00 +0800 Subject: [PATCH 04/23] feat(sentry): implement AsyncHttpTransportFactory for creating AsyncHttpTransport instances --- src/sentry/src/ConfigProvider.php | 3 ++- .../src/Factory/ClientBuilderFactory.php | 14 +++++++--- .../src/Transport/AsyncHttpTransport.php | 1 + .../Transport/AsyncHttpTransportFactory.php | 26 +++++++++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 src/sentry/src/Transport/AsyncHttpTransportFactory.php diff --git a/src/sentry/src/ConfigProvider.php b/src/sentry/src/ConfigProvider.php index 6c13c400c..fec233822 100644 --- a/src/sentry/src/ConfigProvider.php +++ b/src/sentry/src/ConfigProvider.php @@ -47,7 +47,8 @@ public function __invoke(): array 'dependencies' => [ \Sentry\ClientBuilder::class => Factory\ClientBuilderFactory::class, \Sentry\State\HubInterface::class => Factory\HubFactory::class, - \Sentry\HttpClient\HttpClientInterface::class => HttpClient\HttpClientFactory::class, + // \Sentry\HttpClient\HttpClientInterface::class => HttpClient\HttpClientFactory::class, + \Sentry\Transport\TransportInterface::class => Transport\AsyncHttpTransportFactory::class, ], 'listeners' => [ Listener\AmqpExceptionListener::class, diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index a4c1afa1a..6ef95e87f 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -16,6 +16,7 @@ use Psr\Container\ContainerInterface; use Sentry\ClientBuilder; use Sentry\HttpClient\HttpClientInterface; +use Sentry\Transport\TransportInterface; use function Hyperf\Support\env; use function Hyperf\Tappable\tap; @@ -66,11 +67,18 @@ public function __invoke(ContainerInterface $container) $options['environment'] = env('APP_ENV', 'production'); } + // if ( + // ! ($options['http_client'] ?? null) instanceof HttpClientInterface + // && $container->has(HttpClientInterface::class) + // ) { + // $options['http_client'] = $container->get(HttpClientInterface::class); + // } + if ( - ! ($options['http_client'] ?? null) instanceof HttpClientInterface - && $container->has(HttpClientInterface::class) + ! ($options['transport'] ?? null) instanceof TransportInterface + && $container->has(TransportInterface::class) ) { - $options['http_client'] = $container->get(HttpClientInterface::class); + $options['transport'] = $container->get(TransportInterface::class); } return tap( diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 0d7cbeca1..5c11d3d03 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -24,6 +24,7 @@ use Throwable; use function Hyperf\Coroutine\go; +use function Hyperf\Support\msleep; class AsyncHttpTransport implements TransportInterface { diff --git a/src/sentry/src/Transport/AsyncHttpTransportFactory.php b/src/sentry/src/Transport/AsyncHttpTransportFactory.php new file mode 100644 index 000000000..adecbb159 --- /dev/null +++ b/src/sentry/src/Transport/AsyncHttpTransportFactory.php @@ -0,0 +1,26 @@ +get(\Hyperf\Contract\ConfigInterface::class); + $clientBuilder = $container->get(\Sentry\ClientBuilder::class); + $channelSize = $config->get('sentry.transport_channel_size', 65535); + + return new AsyncHttpTransport($clientBuilder, $channelSize); + } +} From e76212930d8d25ec5615eb5d73dac8ddcf9d7764 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:31:03 +0800 Subject: [PATCH 05/23] fix(transport): refactor close method to avoid code duplication --- src/sentry/src/Transport/AsyncHttpTransport.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 5c11d3d03..d230d972a 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -60,6 +60,9 @@ public function send(Event $event): Result public function close(?int $timeout = null): Result { + $this->chan?->close(); + $this->chan = null; + return new Result(ResultStatus::success()); } @@ -94,8 +97,7 @@ protected function loop(): void } } - $this->chan?->close(); - $this->chan = null; + $this->close(); }); $this->workerWatcher ??= Coroutine::create(function () { @@ -106,8 +108,7 @@ protected function loop(): void msleep(100); } - $this->chan?->close(); - $this->chan = null; + $this->close(); } }); } From e20ff5a55a1b36970f2a2d61b5b60b1b2e4621dc Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:31:58 +0800 Subject: [PATCH 06/23] fix(transport): improve close method to prevent unnecessary null assignment --- src/sentry/src/Transport/AsyncHttpTransport.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index d230d972a..a5f71a3e1 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -60,8 +60,12 @@ public function send(Event $event): Result public function close(?int $timeout = null): Result { - $this->chan?->close(); - $this->chan = null; + $chan = $this->chan; + $chan?->close(); + + if ($this->chan === $chan) { + $this->chan = null; + } return new Result(ResultStatus::success()); } From 538da3080688cfe2b5c8f58e9bccd291ad90674e Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:34:36 +0800 Subject: [PATCH 07/23] fix(transport): refactor close method to call closeChannel instead of returning result --- src/sentry/src/Transport/AsyncHttpTransport.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index a5f71a3e1..77901c69e 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -59,6 +59,11 @@ public function send(Event $event): Result } public function close(?int $timeout = null): Result + { + return new Result(ResultStatus::success()); + } + + protected function closeChannel(): void { $chan = $this->chan; $chan?->close(); @@ -66,8 +71,6 @@ public function close(?int $timeout = null): Result if ($this->chan === $chan) { $this->chan = null; } - - return new Result(ResultStatus::success()); } protected function loop(): void @@ -101,7 +104,7 @@ protected function loop(): void } } - $this->close(); + $this->closeChannel(); }); $this->workerWatcher ??= Coroutine::create(function () { @@ -112,7 +115,7 @@ protected function loop(): void msleep(100); } - $this->close(); + $this->closeChannel(); } }); } From 313f49955202bb6bcab7dcf4b256b5ff456b51d6 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:36:37 +0800 Subject: [PATCH 08/23] fix(transport): throw exception in loop method when worker has exited --- src/sentry/src/Transport/AsyncHttpTransport.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 77901c69e..750fde456 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -15,6 +15,7 @@ use Hyperf\Coordinator\CoordinatorManager; use Hyperf\Engine\Channel; use Hyperf\Engine\Coroutine; +use RuntimeException; use Sentry\ClientBuilder; use Sentry\Event; use Sentry\Serializer\PayloadSerializer; @@ -76,7 +77,7 @@ protected function closeChannel(): void protected function loop(): void { if ($this->workerExited) { - return; + throw new RuntimeException('The transport is already closed (the worker exited)'); } if ($this->chan !== null) { From ce985f1dc8cb3112c81aabd60ff2543075b62803 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:39:17 +0800 Subject: [PATCH 09/23] fix(sentry): log error when sending event to Sentry fails --- src/sentry/src/Transport/AsyncHttpTransport.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 750fde456..ed977fd3f 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -98,6 +98,7 @@ protected function loop(): void try { $this->transport->send($event); } catch (Throwable $e) { + $this->clientBuilder->getLogger()?->error('Failed to send event to Sentry: ' . $e->getMessage(), ['exception' => $e]); break; } finally { // Prevent memory leak From e95c6598f8f20266658e66cd0a46895759d80a36 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:43:48 +0800 Subject: [PATCH 10/23] fix(transport): add concurrent limit options to AsyncHttpTransport and refactor coroutine handling --- .../src/Factory/ClientBuilderFactory.php | 2 ++ .../src/Transport/AsyncHttpTransport.php | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index 6ef95e87f..721f59901 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -31,6 +31,8 @@ class ClientBuilderFactory 'integrations', 'http_chanel_size', 'http_concurrent_limit', + 'transport_channel_size', + 'transport_concurrent_limit', 'tracing', ]; diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index ed977fd3f..376869329 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -13,6 +13,7 @@ use Hyperf\Coordinator\Constants; use Hyperf\Coordinator\CoordinatorManager; +use Hyperf\Coroutine\Concurrent; use Hyperf\Engine\Channel; use Hyperf\Engine\Coroutine; use RuntimeException; @@ -24,7 +25,6 @@ use Sentry\Transport\TransportInterface; use Throwable; -use function Hyperf\Coroutine\go; use function Hyperf\Support\msleep; class AsyncHttpTransport implements TransportInterface @@ -37,9 +37,12 @@ class AsyncHttpTransport implements TransportInterface protected ?Coroutine $workerWatcher = null; + protected ?Concurrent $concurrent = null; + public function __construct( protected ClientBuilder $clientBuilder, protected int $channelSize = 65535, + protected int $concurrentLimit = 1000, ) { $this->transport = new \Sentry\Transport\HttpTransport( $this->clientBuilder->getOptions(), @@ -47,6 +50,9 @@ public function __construct( new PayloadSerializer($this->clientBuilder->getOptions()), $this->clientBuilder->getLogger() ); + if ($concurrentLimit > 0) { + $this->concurrent = new Concurrent($concurrentLimit); + } } public function send(Event $event): Result @@ -86,7 +92,7 @@ protected function loop(): void $this->chan = new Channel($this->channelSize); - go(function () { + Coroutine::create(function () { while (true) { /** @var Event|false|null $event */ $event = $this->chan->pop(); @@ -96,7 +102,13 @@ protected function loop(): void } try { - $this->transport->send($event); + $transport = $this->transport; + $callable = static fn () => $transport->send($event); + if ($this->concurrent !== null) { + $this->concurrent->create($callable); + } else { + Coroutine::create($callable); + } } catch (Throwable $e) { $this->clientBuilder->getLogger()?->error('Failed to send event to Sentry: ' . $e->getMessage(), ['exception' => $e]); break; From b0a9ab9157daf1e73dea65f4976f651e3783c9f4 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 10:47:07 +0800 Subject: [PATCH 11/23] fix(sentry): uncomment http channel size and concurrent limit options in ClientBuilderFactory and update AsyncHttpTransportFactory to use them --- src/sentry/src/Factory/ClientBuilderFactory.php | 4 ++-- src/sentry/src/Transport/AsyncHttpTransportFactory.php | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index 721f59901..e777e3366 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -29,8 +29,8 @@ class ClientBuilderFactory 'enable', 'ignore_commands', 'integrations', - 'http_chanel_size', - 'http_concurrent_limit', + // 'http_chanel_size', + // 'http_concurrent_limit', 'transport_channel_size', 'transport_concurrent_limit', 'tracing', diff --git a/src/sentry/src/Transport/AsyncHttpTransportFactory.php b/src/sentry/src/Transport/AsyncHttpTransportFactory.php index adecbb159..de8bca3df 100644 --- a/src/sentry/src/Transport/AsyncHttpTransportFactory.php +++ b/src/sentry/src/Transport/AsyncHttpTransportFactory.php @@ -18,9 +18,11 @@ class AsyncHttpTransportFactory public function __invoke(ContainerInterface $container) { $config = $container->get(\Hyperf\Contract\ConfigInterface::class); - $clientBuilder = $container->get(\Sentry\ClientBuilder::class); - $channelSize = $config->get('sentry.transport_channel_size', 65535); - return new AsyncHttpTransport($clientBuilder, $channelSize); + return new AsyncHttpTransport( + $container->get(\Sentry\ClientBuilder::class), + (int) $config->get('sentry.transport_channel_size', 65535), + (int) $config->get('sentry.transport_concurrent_limit', 1000) + ); } } From 01c37e4bba382e110887262525250ce4a0655f7e Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:16:08 +0800 Subject: [PATCH 12/23] fix(transport): add nullsafe operator to channel pop method in AsyncHttpTransport --- src/sentry/src/Transport/AsyncHttpTransport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 376869329..ae1dc6b4f 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -95,7 +95,7 @@ protected function loop(): void Coroutine::create(function () { while (true) { /** @var Event|false|null $event */ - $event = $this->chan->pop(); + $event = $this->chan?->pop(); if (! $event) { break; From c7383bf024ec05975f90157f846441a8ac1e1d4c Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:22:19 +0800 Subject: [PATCH 13/23] refactor(transport): restructure AsyncHttpTransport by moving transport initialization to makeTransport method and improve error handling in event sending --- .../src/Transport/AsyncHttpTransport.php | 80 ++++++++++--------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index ae1dc6b4f..99a3c74ec 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -29,8 +29,6 @@ class AsyncHttpTransport implements TransportInterface { - protected TransportInterface $transport; - protected ?Channel $chan = null; protected bool $workerExited = false; @@ -44,12 +42,6 @@ public function __construct( protected int $channelSize = 65535, protected int $concurrentLimit = 1000, ) { - $this->transport = new \Sentry\Transport\HttpTransport( - $this->clientBuilder->getOptions(), - $this->clientBuilder->getHttpClient(), - new PayloadSerializer($this->clientBuilder->getOptions()), - $this->clientBuilder->getLogger() - ); if ($concurrentLimit > 0) { $this->concurrent = new Concurrent($concurrentLimit); } @@ -70,16 +62,6 @@ public function close(?int $timeout = null): Result return new Result(ResultStatus::success()); } - protected function closeChannel(): void - { - $chan = $this->chan; - $chan?->close(); - - if ($this->chan === $chan) { - $this->chan = null; - } - } - protected function loop(): void { if ($this->workerExited) { @@ -94,27 +76,33 @@ protected function loop(): void Coroutine::create(function () { while (true) { - /** @var Event|false|null $event */ - $event = $this->chan?->pop(); + $transport = $this->makeTransport(); + $logger = $this->clientBuilder->getLogger(); - if (! $event) { - break; - } + while (true) { + /** @var Event|false|null $event */ + $event = $this->chan?->pop(); + + if (! $event) { + break 2; + } - try { - $transport = $this->transport; - $callable = static fn () => $transport->send($event); - if ($this->concurrent !== null) { - $this->concurrent->create($callable); - } else { - Coroutine::create($callable); + 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; } - } catch (Throwable $e) { - $this->clientBuilder->getLogger()?->error('Failed to send event to Sentry: ' . $e->getMessage(), ['exception' => $e]); - break; - } finally { - // Prevent memory leak - $event = null; } } @@ -133,4 +121,24 @@ protected function loop(): void } }); } + + protected function makeTransport(): TransportInterface + { + 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; + } + } } From 130be04c7868137ff86433c9c15291611d35723f Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:17:12 +0800 Subject: [PATCH 14/23] refactor(transport): replace AsyncHttpTransportFactory with direct instantiation in AsyncHttpTransport and update constructor to use container for configuration --- src/sentry/src/ConfigProvider.php | 2 +- .../src/Transport/AsyncHttpTransport.php | 15 ++++++++-- .../Transport/AsyncHttpTransportFactory.php | 28 ------------------- 3 files changed, 13 insertions(+), 32 deletions(-) delete mode 100644 src/sentry/src/Transport/AsyncHttpTransportFactory.php diff --git a/src/sentry/src/ConfigProvider.php b/src/sentry/src/ConfigProvider.php index fec233822..73d229343 100644 --- a/src/sentry/src/ConfigProvider.php +++ b/src/sentry/src/ConfigProvider.php @@ -48,7 +48,7 @@ public function __invoke(): array \Sentry\ClientBuilder::class => Factory\ClientBuilderFactory::class, \Sentry\State\HubInterface::class => Factory\HubFactory::class, // \Sentry\HttpClient\HttpClientInterface::class => HttpClient\HttpClientFactory::class, - \Sentry\Transport\TransportInterface::class => Transport\AsyncHttpTransportFactory::class, + \Sentry\Transport\TransportInterface::class => Transport\AsyncHttpTransport::class, ], 'listeners' => [ Listener\AmqpExceptionListener::class, diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 99a3c74ec..7292e9ba3 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -16,6 +16,7 @@ use Hyperf\Coroutine\Concurrent; use Hyperf\Engine\Channel; use Hyperf\Engine\Coroutine; +use Psr\Container\ContainerInterface; use RuntimeException; use Sentry\ClientBuilder; use Sentry\Event; @@ -37,11 +38,19 @@ class AsyncHttpTransport implements TransportInterface protected ?Concurrent $concurrent = null; + protected ?ClientBuilder $clientBuilder = null; + + protected int $channelSize = 65535; + public function __construct( - protected ClientBuilder $clientBuilder, - protected int $channelSize = 65535, - protected int $concurrentLimit = 1000, + 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); } diff --git a/src/sentry/src/Transport/AsyncHttpTransportFactory.php b/src/sentry/src/Transport/AsyncHttpTransportFactory.php deleted file mode 100644 index de8bca3df..000000000 --- a/src/sentry/src/Transport/AsyncHttpTransportFactory.php +++ /dev/null @@ -1,28 +0,0 @@ -get(\Hyperf\Contract\ConfigInterface::class); - - return new AsyncHttpTransport( - $container->get(\Sentry\ClientBuilder::class), - (int) $config->get('sentry.transport_channel_size', 65535), - (int) $config->get('sentry.transport_concurrent_limit', 1000) - ); - } -} From 286a88d74ca59e441c78340107e6933bf7bee8a4 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:19:34 +0800 Subject: [PATCH 15/23] fix(transport): handle closed transport gracefully and improve logger retrieval in AsyncHttpTransport --- src/sentry/src/Transport/AsyncHttpTransport.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 7292e9ba3..23aba4a67 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -17,7 +17,6 @@ use Hyperf\Engine\Channel; use Hyperf\Engine\Coroutine; use Psr\Container\ContainerInterface; -use RuntimeException; use Sentry\ClientBuilder; use Sentry\Event; use Sentry\Serializer\PayloadSerializer; @@ -74,7 +73,7 @@ public function close(?int $timeout = null): Result protected function loop(): void { if ($this->workerExited) { - throw new RuntimeException('The transport is already closed (the worker exited)'); + return; } if ($this->chan !== null) { @@ -86,7 +85,7 @@ protected function loop(): void Coroutine::create(function () { while (true) { $transport = $this->makeTransport(); - $logger = $this->clientBuilder->getLogger(); + $logger = $this->clientBuilder?->getLogger(); while (true) { /** @var Event|false|null $event */ @@ -133,6 +132,8 @@ protected function loop(): void protected function makeTransport(): TransportInterface { + $this->clientBuilder ??= $this->container->get(ClientBuilder::class); + return new \Sentry\Transport\HttpTransport( $this->clientBuilder->getOptions(), $this->clientBuilder->getHttpClient(), From 5f3bb34eb2a45533174fa2993b04a400af47eb6f Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:27:03 +0800 Subject: [PATCH 16/23] refactor(transport): rename transport methods for clarity and mark HttpClient and HttpClientFactory as deprecated --- src/sentry/src/HttpClient/HttpClient.php | 3 +++ src/sentry/src/HttpClient/HttpClientFactory.php | 3 +++ src/sentry/src/Transport/AsyncHttpTransport.php | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/sentry/src/HttpClient/HttpClient.php b/src/sentry/src/HttpClient/HttpClient.php index 6ccb87c47..3fe0a272f 100644 --- a/src/sentry/src/HttpClient/HttpClient.php +++ b/src/sentry/src/HttpClient/HttpClient.php @@ -24,6 +24,9 @@ use function Hyperf\Support\msleep; use function Hyperf\Tappable\tap; +/** + * @deprecated since v3.1, will be removed in v3.2 + */ class HttpClient extends \Sentry\HttpClient\HttpClient { protected ?Channel $chan = null; diff --git a/src/sentry/src/HttpClient/HttpClientFactory.php b/src/sentry/src/HttpClient/HttpClientFactory.php index 8e56f3e46..e3aee60cb 100644 --- a/src/sentry/src/HttpClient/HttpClientFactory.php +++ b/src/sentry/src/HttpClient/HttpClientFactory.php @@ -15,6 +15,9 @@ use Hyperf\Contract\ConfigInterface; use Psr\Container\ContainerInterface; +/** + * @deprecated since v3.1, will be removed in v3.2 + */ class HttpClientFactory { public function __invoke(ContainerInterface $container) diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/AsyncHttpTransport.php index 23aba4a67..4121a5d4b 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/AsyncHttpTransport.php @@ -84,7 +84,7 @@ protected function loop(): void Coroutine::create(function () { while (true) { - $transport = $this->makeTransport(); + $transport = $this->makeHttpTransport(); $logger = $this->clientBuilder?->getLogger(); while (true) { @@ -130,7 +130,7 @@ protected function loop(): void }); } - protected function makeTransport(): TransportInterface + protected function makeHttpTransport(): TransportInterface { $this->clientBuilder ??= $this->container->get(ClientBuilder::class); From 8f3200d41bb64c4a8ee0ad952358d1db93bb530f Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:32:28 +0800 Subject: [PATCH 17/23] feat(sentry): add transport channel size and concurrent limit configuration options --- src/sentry/publish/sentry.php | 5 +++-- src/sentry/src/Factory/ClientBuilderFactory.php | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sentry/publish/sentry.php b/src/sentry/publish/sentry.php index c19debaad..e812aa95e 100644 --- a/src/sentry/publish/sentry.php +++ b/src/sentry/publish/sentry.php @@ -128,7 +128,8 @@ 'timezone' => env('SENTRY_CRONS_TIMEZONE', date_default_timezone_get()), ], + 'transport_channel_size' => (int) env('SENTRY_TRANSPORT_CHANNEL_SIZE', 65535), + 'transport_concurrent_limit' => (int) env('SENTRY_TRANSPORT_CONCURRENT_LIMIT', 1000), + 'http_timeout' => (float) env('SENTRY_HTTP_TIMEOUT', 2.0), - 'http_chanel_size' => (int) env('SENTRY_HTTP_CHANEL_SIZE', 65535), - 'http_concurrent_limit' => (int) env('SENTRY_HTTP_CONCURRENT_LIMIT', 100), ]; diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index e777e3366..16e11b8d8 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -29,8 +29,6 @@ class ClientBuilderFactory 'enable', 'ignore_commands', 'integrations', - // 'http_chanel_size', - // 'http_concurrent_limit', 'transport_channel_size', 'transport_concurrent_limit', 'tracing', From a71c19fd6ca368bd99608a37b93968b9effc74f0 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:33:22 +0800 Subject: [PATCH 18/23] Remove unused HttpClientInterface references Eliminated the import and commented-out code related to Sentry\HttpClient\HttpClientInterface in ClientBuilderFactory, as it is no longer used. --- src/sentry/src/Factory/ClientBuilderFactory.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index 16e11b8d8..bd588bced 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -15,7 +15,6 @@ use Hyperf\Contract\ConfigInterface; use Psr\Container\ContainerInterface; use Sentry\ClientBuilder; -use Sentry\HttpClient\HttpClientInterface; use Sentry\Transport\TransportInterface; use function Hyperf\Support\env; @@ -67,13 +66,6 @@ public function __invoke(ContainerInterface $container) $options['environment'] = env('APP_ENV', 'production'); } - // if ( - // ! ($options['http_client'] ?? null) instanceof HttpClientInterface - // && $container->has(HttpClientInterface::class) - // ) { - // $options['http_client'] = $container->get(HttpClientInterface::class); - // } - if ( ! ($options['transport'] ?? null) instanceof TransportInterface && $container->has(TransportInterface::class) From 3d1a2bc886362057d0081bb6991a762a8a5b0f33 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:39:12 +0800 Subject: [PATCH 19/23] refactor(transport): replace AsyncHttpTransport with CoHttpTransport and update transport interface mapping --- src/sentry/src/ConfigProvider.php | 2 +- .../Transport/{AsyncHttpTransport.php => CoHttpTransport.php} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/sentry/src/Transport/{AsyncHttpTransport.php => CoHttpTransport.php} (98%) diff --git a/src/sentry/src/ConfigProvider.php b/src/sentry/src/ConfigProvider.php index 73d229343..a56a7c2b2 100644 --- a/src/sentry/src/ConfigProvider.php +++ b/src/sentry/src/ConfigProvider.php @@ -48,7 +48,7 @@ public function __invoke(): array \Sentry\ClientBuilder::class => Factory\ClientBuilderFactory::class, \Sentry\State\HubInterface::class => Factory\HubFactory::class, // \Sentry\HttpClient\HttpClientInterface::class => HttpClient\HttpClientFactory::class, - \Sentry\Transport\TransportInterface::class => Transport\AsyncHttpTransport::class, + \Sentry\Transport\TransportInterface::class => Transport\CoHttpTransport::class, ], 'listeners' => [ Listener\AmqpExceptionListener::class, diff --git a/src/sentry/src/Transport/AsyncHttpTransport.php b/src/sentry/src/Transport/CoHttpTransport.php similarity index 98% rename from src/sentry/src/Transport/AsyncHttpTransport.php rename to src/sentry/src/Transport/CoHttpTransport.php index 4121a5d4b..b5fc16d35 100644 --- a/src/sentry/src/Transport/AsyncHttpTransport.php +++ b/src/sentry/src/Transport/CoHttpTransport.php @@ -27,7 +27,7 @@ use function Hyperf\Support\msleep; -class AsyncHttpTransport implements TransportInterface +class CoHttpTransport implements TransportInterface { protected ?Channel $chan = null; From 60d6d9cea4786b69f41e2f5f9b427fe1893b5bec Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:40:49 +0800 Subject: [PATCH 20/23] refactor(factory): mark http_channel_size and http_concurrent_limit as deprecated --- src/sentry/src/Factory/ClientBuilderFactory.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index bd588bced..03783d40d 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -28,6 +28,8 @@ class ClientBuilderFactory 'enable', 'ignore_commands', 'integrations', + 'http_chanel_size', // deprecated, will be removed in v3.2 + 'http_concurrent_limit', // deprecated, will be removed in v3.2 'transport_channel_size', 'transport_concurrent_limit', 'tracing', From 6a19aeb6926adadcb400998ceff720c11c5702be Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:41:13 +0800 Subject: [PATCH 21/23] refactor(factory): add comments to clarify transport selection logic --- src/sentry/src/Factory/ClientBuilderFactory.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index 03783d40d..dacc35106 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -68,6 +68,9 @@ public function __invoke(ContainerInterface $container) $options['environment'] = env('APP_ENV', 'production'); } + // If the user has not set a transport we check if one is bound in the container + // and use that one. This allows us to use the CoHttpTransport as the default + // transport instead of the default Guzzle one. if ( ! ($options['transport'] ?? null) instanceof TransportInterface && $container->has(TransportInterface::class) From b1d1492bba50d93562e23e3d306f858f59be8af3 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:49:55 +0800 Subject: [PATCH 22/23] refactor(transport): simplify transport initialization and remove unused container dependency --- .../src/Factory/ClientBuilderFactory.php | 25 +++++++++++-------- src/sentry/src/Transport/CoHttpTransport.php | 12 +++------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index dacc35106..0f58c0fe5 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -68,19 +68,22 @@ public function __invoke(ContainerInterface $container) $options['environment'] = env('APP_ENV', 'production'); } - // If the user has not set a transport we check if one is bound in the container - // and use that one. This allows us to use the CoHttpTransport as the default - // transport instead of the default Guzzle one. - if ( - ! ($options['transport'] ?? null) instanceof TransportInterface - && $container->has(TransportInterface::class) - ) { - $options['transport'] = $container->get(TransportInterface::class); - } - return tap( ClientBuilder::create($options), - fn (ClientBuilder $clientBuilder) => $clientBuilder->setSdkIdentifier(Version::getSdkIdentifier())->setSdkVersion(Version::getSdkVersion()) + function (ClientBuilder $clientBuilder) use ($options, $container) { + // If the user has not set a transport we check if one is bound in the container + // and use that one. This allows us to use the CoHttpTransport as the default + // transport instead of the default Guzzle one. + if ( + ! ($options['transport'] ?? null) instanceof TransportInterface + && $container->has(TransportInterface::class) + ) { + $clientBuilder->setTransport($container->get(TransportInterface::class)); + } + + $clientBuilder->setSdkIdentifier(Version::getSdkIdentifier()) + ->setSdkVersion(Version::getSdkVersion()); + } ); } } diff --git a/src/sentry/src/Transport/CoHttpTransport.php b/src/sentry/src/Transport/CoHttpTransport.php index b5fc16d35..3b549b29f 100644 --- a/src/sentry/src/Transport/CoHttpTransport.php +++ b/src/sentry/src/Transport/CoHttpTransport.php @@ -11,12 +11,12 @@ namespace FriendsOfHyperf\Sentry\Transport; +use Hyperf\Contract\ConfigInterface; 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; @@ -37,14 +37,12 @@ class CoHttpTransport implements TransportInterface protected ?Concurrent $concurrent = null; - protected ?ClientBuilder $clientBuilder = null; - protected int $channelSize = 65535; public function __construct( - protected ContainerInterface $container, + protected ClientBuilder $clientBuilder, + protected ConfigInterface $config, ) { - $config = $this->container->get('config'); $channelSize = (int) $config->get('sentry.transport_channel_size', 65535); if ($channelSize > 0) { $this->channelSize = $channelSize; @@ -85,7 +83,7 @@ protected function loop(): void Coroutine::create(function () { while (true) { $transport = $this->makeHttpTransport(); - $logger = $this->clientBuilder?->getLogger(); + $logger = $this->clientBuilder->getLogger(); while (true) { /** @var Event|false|null $event */ @@ -132,8 +130,6 @@ protected function loop(): void protected function makeHttpTransport(): TransportInterface { - $this->clientBuilder ??= $this->container->get(ClientBuilder::class); - return new \Sentry\Transport\HttpTransport( $this->clientBuilder->getOptions(), $this->clientBuilder->getHttpClient(), From 2ac62351308da7ffb0614207983026b22533065e Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:55:02 +0800 Subject: [PATCH 23/23] Revert "refactor(transport): simplify transport initialization and remove unused container dependency" This reverts commit b1d1492bba50d93562e23e3d306f858f59be8af3. --- .../src/Factory/ClientBuilderFactory.php | 25 ++++++++----------- src/sentry/src/Transport/CoHttpTransport.php | 12 ++++++--- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index 0f58c0fe5..dacc35106 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -68,22 +68,19 @@ public function __invoke(ContainerInterface $container) $options['environment'] = env('APP_ENV', 'production'); } + // If the user has not set a transport we check if one is bound in the container + // and use that one. This allows us to use the CoHttpTransport as the default + // transport instead of the default Guzzle one. + if ( + ! ($options['transport'] ?? null) instanceof TransportInterface + && $container->has(TransportInterface::class) + ) { + $options['transport'] = $container->get(TransportInterface::class); + } + return tap( ClientBuilder::create($options), - function (ClientBuilder $clientBuilder) use ($options, $container) { - // If the user has not set a transport we check if one is bound in the container - // and use that one. This allows us to use the CoHttpTransport as the default - // transport instead of the default Guzzle one. - if ( - ! ($options['transport'] ?? null) instanceof TransportInterface - && $container->has(TransportInterface::class) - ) { - $clientBuilder->setTransport($container->get(TransportInterface::class)); - } - - $clientBuilder->setSdkIdentifier(Version::getSdkIdentifier()) - ->setSdkVersion(Version::getSdkVersion()); - } + fn (ClientBuilder $clientBuilder) => $clientBuilder->setSdkIdentifier(Version::getSdkIdentifier())->setSdkVersion(Version::getSdkVersion()) ); } } diff --git a/src/sentry/src/Transport/CoHttpTransport.php b/src/sentry/src/Transport/CoHttpTransport.php index 3b549b29f..b5fc16d35 100644 --- a/src/sentry/src/Transport/CoHttpTransport.php +++ b/src/sentry/src/Transport/CoHttpTransport.php @@ -11,12 +11,12 @@ namespace FriendsOfHyperf\Sentry\Transport; -use Hyperf\Contract\ConfigInterface; 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; @@ -37,12 +37,14 @@ class CoHttpTransport implements TransportInterface protected ?Concurrent $concurrent = null; + protected ?ClientBuilder $clientBuilder = null; + protected int $channelSize = 65535; public function __construct( - protected ClientBuilder $clientBuilder, - protected ConfigInterface $config, + protected ContainerInterface $container, ) { + $config = $this->container->get('config'); $channelSize = (int) $config->get('sentry.transport_channel_size', 65535); if ($channelSize > 0) { $this->channelSize = $channelSize; @@ -83,7 +85,7 @@ protected function loop(): void Coroutine::create(function () { while (true) { $transport = $this->makeHttpTransport(); - $logger = $this->clientBuilder->getLogger(); + $logger = $this->clientBuilder?->getLogger(); while (true) { /** @var Event|false|null $event */ @@ -130,6 +132,8 @@ protected function loop(): void protected function makeHttpTransport(): TransportInterface { + $this->clientBuilder ??= $this->container->get(ClientBuilder::class); + return new \Sentry\Transport\HttpTransport( $this->clientBuilder->getOptions(), $this->clientBuilder->getHttpClient(),