diff --git a/src/sentry/src/Listener/AmqpExceptionListener.php b/src/sentry/src/Listener/AmqpExceptionListener.php deleted file mode 100644 index 592e93703..000000000 --- a/src/sentry/src/Listener/AmqpExceptionListener.php +++ /dev/null @@ -1,47 +0,0 @@ -switcher->isEnable('amqp')) { - return; - } - - match ($event::class) { - Event\FailToConsume::class => $this->captureException($event->getThrowable()), - default => $this->setupSentrySdk(), - }; - - match ($event::class) { - Event\AfterConsume::class, - Event\FailToConsume::class => $this->flushEvents(), - default => null, - }; - } -} diff --git a/src/sentry/src/Listener/AsyncQueueExceptionListener.php b/src/sentry/src/Listener/AsyncQueueExceptionListener.php deleted file mode 100644 index ae0b1551b..000000000 --- a/src/sentry/src/Listener/AsyncQueueExceptionListener.php +++ /dev/null @@ -1,50 +0,0 @@ -switcher->isEnable('async_queue')) { - return; - } - - match ($event::class) { - Event\RetryHandle::class, - Event\FailedHandle::class => $this->captureException($event->getThrowable()), - default => $this->setupSentrySdk(), - }; - - match ($event::class) { - Event\AfterHandle::class, - Event\RetryHandle::class, - Event\FailedHandle::class => $this->flushEvents(), - default => null, - }; - } -} diff --git a/src/sentry/src/Listener/CaptureExceptionListener.php b/src/sentry/src/Listener/CaptureExceptionListener.php deleted file mode 100644 index 1f56dd7e3..000000000 --- a/src/sentry/src/Listener/CaptureExceptionListener.php +++ /dev/null @@ -1,69 +0,0 @@ -captureException($throwable); - } catch (Throwable $e) { - $this->container->get(StdoutLoggerInterface::class)->error((string) $e); - } finally { - $hub->getClient()?->flush(); - } - } - - protected function setupSentrySdk(): void - { - if (Context::has(static::SETUP)) { - if ($this->container->has(StdoutLoggerInterface::class)) { - $this->container->get(StdoutLoggerInterface::class)->warning('SentrySdk has been setup.'); - } - - return; - } - - SentrySdk::init(); - Context::set(static::SETUP, true); - } - - protected function flushEvents(): void - { - Integration::flushEvents(); - } -} diff --git a/src/sentry/src/Listener/CommandExceptionListener.php b/src/sentry/src/Listener/CommandExceptionListener.php deleted file mode 100644 index 76f186416..000000000 --- a/src/sentry/src/Listener/CommandExceptionListener.php +++ /dev/null @@ -1,42 +0,0 @@ -switcher->isEnable('command')) { - return; - } - - match ($event::class) { - Event\FailToHandle::class => $this->captureException($event->getThrowable()), - Event\AfterExecute::class => $this->flushEvents(), - default => $this->setupSentrySdk(), - }; - } -} diff --git a/src/sentry/src/Listener/CrontabExceptionListener.php b/src/sentry/src/Listener/CrontabExceptionListener.php deleted file mode 100644 index 0b09fcbe9..000000000 --- a/src/sentry/src/Listener/CrontabExceptionListener.php +++ /dev/null @@ -1,52 +0,0 @@ -switcher->isEnable('crontab')) { - return; - } - - match ($event::class) { - Event\FailToExecute::class => $this->captureException($event->throwable), - default => $this->setupSentrySdk(), - }; - - match ($event::class) { - Event\AfterExecute::class, - Event\FailToExecute::class => $this->flushEvents(), - default => null, - }; - } -} diff --git a/src/sentry/src/Listener/DbQueryListener.php b/src/sentry/src/Listener/DbQueryListener.php deleted file mode 100644 index b3ae769a9..000000000 --- a/src/sentry/src/Listener/DbQueryListener.php +++ /dev/null @@ -1,102 +0,0 @@ - $this->queryExecutedHandler($event), - $event instanceof TransactionBeginning => $this->transactionHandler($event), - $event instanceof TransactionCommitted => $this->transactionHandler($event), - $event instanceof TransactionRolledBack => $this->transactionHandler($event), - default => null - }; - } - - /** - * @param object|QueryExecuted $event - */ - protected function queryExecutedHandler(object $event): void - { - if (! $this->switcher->isBreadcrumbEnable('sql_queries')) { - return; - } - - $data = ['connectionName' => $event->connectionName]; - - if ($event->time !== null) { - $data['executionTimeMs'] = $event->time; - } - - if ($this->switcher->isBreadcrumbEnable('sql_bindings')) { - $data['bindings'] = $event->bindings; - } - - Integration::addBreadcrumb(new Breadcrumb( - Breadcrumb::LEVEL_INFO, - Breadcrumb::TYPE_DEFAULT, - 'sql.query', - $event->sql, - $data - )); - } - - /** - * @param ConnectionEvent|object $event - */ - protected function transactionHandler(object $event): void - { - if (! $this->switcher->isBreadcrumbEnable('sql_transaction')) { - return; - } - - $data = [ - 'connectionName' => $event->connectionName, - ]; - - Integration::addBreadcrumb(new Breadcrumb( - Breadcrumb::LEVEL_INFO, - Breadcrumb::TYPE_DEFAULT, - 'sql.transaction', - $event::class, - $data - )); - } -} diff --git a/src/sentry/src/Listener/EventListener.php b/src/sentry/src/Listener/EventListener.php new file mode 100644 index 000000000..fd213f0be --- /dev/null +++ b/src/sentry/src/Listener/EventListener.php @@ -0,0 +1,508 @@ + $this->handleBootApplication($event), + + // Database events + QueryExecuted::class => $this->handleDbQuery($event), + TransactionBeginning::class, + TransactionCommitted::class, + TransactionRolledBack::class => $this->handleDbTransaction($event), + + // Redis events + CommandExecuted::class => $this->handleRedisCommand($event), + + // Request events + RequestReceived::class, + RpcRequestReceived::class => $this->handleRequestReceived($event), + RequestTerminated::class, + RpcRequestTerminated::class => $this->handleRequestTerminated($event), + + // Command events + CommandEvent\BeforeHandle::class => $this->handleCommandBefore($event), + CommandEvent\FailToHandle::class => $this->handleCommandFail($event), + CommandEvent\AfterExecute::class => $this->handleCommandAfter($event), + + // Async Queue events + AsyncQueueEvent\BeforeHandle::class => $this->handleAsyncQueueBefore($event), + AsyncQueueEvent\AfterHandle::class => $this->handleAsyncQueueAfter($event), + AsyncQueueEvent\RetryHandle::class => $this->handleAsyncQueueRetry($event), + AsyncQueueEvent\FailedHandle::class => $this->handleAsyncQueueFailed($event), + + // Crontab events + CrontabEvent\BeforeExecute::class => $this->handleCrontabBefore($event), + CrontabEvent\AfterExecute::class => $this->handleCrontabAfter($event), + CrontabEvent\FailToExecute::class => $this->handleCrontabFail($event), + + // AMQP events + AmqpEvent\BeforeConsume::class => $this->handleAmqpBefore($event), + AmqpEvent\AfterConsume::class => $this->handleAmqpAfter($event), + AmqpEvent\FailToConsume::class => $this->handleAmqpFail($event), + + // Kafka events + KafkaEvent\BeforeConsume::class => $this->handleKafkaBefore($event), + KafkaEvent\AfterConsume::class => $this->handleKafkaAfter($event), + KafkaEvent\FailToConsume::class => $this->handleKafkaFail($event), + + default => null, + }; + } + + protected function captureException($throwable): void + { + if (! $throwable instanceof Throwable) { + return; + } + + $hub = SentrySdk::getCurrentHub(); + + try { + $hub->captureException($throwable); + } catch (Throwable $e) { + $this->container->get(StdoutLoggerInterface::class)->error((string) $e); + } finally { + $hub->getClient()?->flush(); + } + } + + protected function setupSentrySdk(): void + { + if (Context::has(static::SETUP)) { + if ($this->container->has(StdoutLoggerInterface::class)) { + $this->container->get(StdoutLoggerInterface::class)->warning('SentrySdk has been setup.'); + } + + return; + } + + SentrySdk::init(); + Context::set(static::SETUP, true); + } + + protected function flushEvents(): void + { + Integration::flushEvents(); + } + + protected function handleBootApplication(object $event): void + { + $this->setupRequestLifecycle(); + $this->setupRedisEventEnable(); + } + + protected function setupRequestLifecycle(): void + { + $keys = [ + 'sentry.enable.amqp', + 'sentry.enable.async_queue', + 'sentry.enable.command', + 'sentry.enable.crontab', + 'sentry.enable.kafka', + 'sentry.enable.request', + 'sentry.breadcrumbs.cache', + 'sentry.breadcrumbs.sql_queries', + 'sentry.breadcrumbs.sql_bindings', + 'sentry.breadcrumbs.sql_transaction', + 'sentry.breadcrumbs.redis', + 'sentry.breadcrumbs.guzzle', + 'sentry.breadcrumbs.logs', + 'sentry.enable_tracing', + 'sentry.tracing.enable.amqp', + 'sentry.tracing.enable.async_queue', + 'sentry.tracing.enable.cache', + 'sentry.tracing.enable.command', + 'sentry.tracing.enable.crontab', + 'sentry.tracing.enable.kafka', + 'sentry.tracing.enable.request', + 'sentry.tracing.spans.coroutine', + 'sentry.tracing.spans.db', + 'sentry.tracing.spans.elasticsearch', + 'sentry.tracing.spans.guzzle', + 'sentry.tracing.spans.rpc', + 'sentry.tracing.spans.redis', + 'sentry.tracing.spans.sql_queries', + ]; + + foreach ($keys as $key) { + if (! $this->config->has($key)) { + $this->config->set($key, true); + } + } + + if ( + ! $this->switcher->isEnable('request') + && ! $this->switcher->isTracingEnable('request') + ) { + return; + } + + $servers = $this->config->get('server.servers', []); + + foreach ($servers as &$server) { + $callbacks = $server['callbacks'] ?? []; + $handler = $callbacks[Event::ON_REQUEST][0] ?? $callbacks[Event::ON_RECEIVE][0] ?? null; + + if (! $handler) { + continue; + } + + if ( + is_a($handler, HttpServer::class, true) + || is_a($handler, RpcServer::class, true) + ) { + $server['options'] ??= []; + $server['options']['enable_request_lifecycle'] = true; + } + } + + $this->config->set('server.servers', $servers); + } + + protected function setupRedisEventEnable(): void + { + if (! $this->config->has('redis')) { + return; + } + + foreach ($this->config->get('redis', []) as $pool => $_) { + $this->config->set("redis.{$pool}.event.enable", true); + } + } + + protected function handleDbQuery(object $event): void + { + if (! $this->switcher->isBreadcrumbEnable('sql_queries')) { + return; + } + + $data = ['connectionName' => $event->connectionName]; + + if ($event->time !== null) { + $data['executionTimeMs'] = $event->time; + } + + if ($this->switcher->isBreadcrumbEnable('sql_bindings')) { + $data['bindings'] = $event->bindings; + } + + Integration::addBreadcrumb(new Breadcrumb( + Breadcrumb::LEVEL_INFO, + Breadcrumb::TYPE_DEFAULT, + 'sql.query', + $event->sql, + $data + )); + } + + protected function handleDbTransaction(object $event): void + { + if (! $this->switcher->isBreadcrumbEnable('sql_transaction')) { + return; + } + + $data = [ + 'connectionName' => $event->connectionName, + ]; + + Integration::addBreadcrumb(new Breadcrumb( + Breadcrumb::LEVEL_INFO, + Breadcrumb::TYPE_DEFAULT, + 'sql.transaction', + $event::class, + $data + )); + } + + protected function handleRedisCommand(object $event): void + { + if ( + ! $this->switcher->isBreadcrumbEnable('redis') + || ! $event instanceof CommandExecuted + ) { + return; + } + + Integration::addBreadcrumb(new Breadcrumb( + Breadcrumb::LEVEL_INFO, + Breadcrumb::TYPE_DEFAULT, + 'redis', + $event->command, + [ + 'arguments' => $event->parameters, + 'result' => $event->result, + 'duration' => $event->time * 1000, + ] + )); + } + + protected function handleRequestReceived(object $event): void + { + if (! $this->switcher->isEnable('request')) { + return; + } + + $this->setupSentrySdk(); + } + + protected function handleRequestTerminated(object $event): void + { + if (! $this->switcher->isEnable('request')) { + return; + } + + $this->captureException($event->exception); + $this->flushEvents(); + } + + protected function handleCommandBefore(object $event): void + { + if (! $this->switcher->isEnable('command')) { + return; + } + + $this->setupSentrySdk(); + } + + protected function handleCommandFail(object $event): void + { + if (! $this->switcher->isEnable('command')) { + return; + } + + $this->captureException($event->getThrowable()); + } + + protected function handleCommandAfter(object $event): void + { + if (! $this->switcher->isEnable('command')) { + return; + } + + $this->flushEvents(); + } + + protected function handleAsyncQueueBefore(object $event): void + { + if (! $this->switcher->isEnable('async_queue')) { + return; + } + + $this->setupSentrySdk(); + } + + protected function handleAsyncQueueAfter(object $event): void + { + if (! $this->switcher->isEnable('async_queue')) { + return; + } + + $this->flushEvents(); + } + + protected function handleAsyncQueueRetry(object $event): void + { + if (! $this->switcher->isEnable('async_queue')) { + return; + } + + $this->captureException($event->getThrowable()); + $this->flushEvents(); + } + + protected function handleAsyncQueueFailed(object $event): void + { + if (! $this->switcher->isEnable('async_queue')) { + return; + } + + $this->captureException($event->getThrowable()); + $this->flushEvents(); + } + + protected function handleCrontabBefore(object $event): void + { + if (! $this->switcher->isEnable('crontab')) { + return; + } + + $this->setupSentrySdk(); + } + + protected function handleCrontabAfter(object $event): void + { + if (! $this->switcher->isEnable('crontab')) { + return; + } + + $this->flushEvents(); + } + + protected function handleCrontabFail(object $event): void + { + if (! $this->switcher->isEnable('crontab')) { + return; + } + + $this->captureException($event->throwable); + $this->flushEvents(); + } + + protected function handleAmqpBefore(object $event): void + { + if (! $this->switcher->isEnable('amqp')) { + return; + } + + $this->setupSentrySdk(); + } + + protected function handleAmqpAfter(object $event): void + { + if (! $this->switcher->isEnable('amqp')) { + return; + } + + $this->flushEvents(); + } + + protected function handleAmqpFail(object $event): void + { + if (! $this->switcher->isEnable('amqp')) { + return; + } + + $this->captureException($event->getThrowable()); + $this->flushEvents(); + } + + protected function handleKafkaBefore(object $event): void + { + if (! $this->switcher->isEnable('kafka')) { + return; + } + + $this->setupSentrySdk(); + } + + protected function handleKafkaAfter(object $event): void + { + if (! $this->switcher->isEnable('kafka')) { + return; + } + + $this->flushEvents(); + } + + protected function handleKafkaFail(object $event): void + { + if (! $this->switcher->isEnable('kafka')) { + return; + } + + $this->captureException($event->getThrowable()); + $this->flushEvents(); + } +} \ No newline at end of file diff --git a/src/sentry/src/Listener/KafkaExceptionListener.php b/src/sentry/src/Listener/KafkaExceptionListener.php deleted file mode 100644 index 6a4f4a2b9..000000000 --- a/src/sentry/src/Listener/KafkaExceptionListener.php +++ /dev/null @@ -1,47 +0,0 @@ -switcher->isEnable('kafka')) { - return; - } - - match ($event::class) { - Event\FailToConsume::class => $this->captureException($event->getThrowable()), - default => $this->setupSentrySdk(), - }; - - match ($event::class) { - Event\AfterConsume::class, - Event\FailToConsume::class => $this->flushEvents(), - default => null, - }; - } -} diff --git a/src/sentry/src/Listener/RedisCommandExecutedListener.php b/src/sentry/src/Listener/RedisCommandExecutedListener.php deleted file mode 100644 index 218feec12..000000000 --- a/src/sentry/src/Listener/RedisCommandExecutedListener.php +++ /dev/null @@ -1,57 +0,0 @@ -switcher->isBreadcrumbEnable('redis') - || ! $event instanceof CommandExecuted - ) { - return; - } - - Integration::addBreadcrumb(new Breadcrumb( - Breadcrumb::LEVEL_INFO, - Breadcrumb::TYPE_DEFAULT, - 'redis', - $event->command, - [ - 'arguments' => $event->parameters, - 'result' => $event->result, - 'duration' => $event->time * 1000, - ] - )); - } -} diff --git a/src/sentry/src/Listener/RequestExceptionListener.php b/src/sentry/src/Listener/RequestExceptionListener.php deleted file mode 100644 index 58f82d4fa..000000000 --- a/src/sentry/src/Listener/RequestExceptionListener.php +++ /dev/null @@ -1,51 +0,0 @@ -switcher->isEnable('request')) { - return; - } - - match ($event::class) { - RequestTerminated::class, RpcRequestTerminated::class => $this->captureException($event->exception), - default => $this->setupSentrySdk(), - }; - - match ($event::class) { - RequestTerminated::class, - RpcRequestTerminated::class => $this->flushEvents(), - default => null, - }; - } -} diff --git a/src/sentry/src/Listener/SetRedisEventEnableListener.php b/src/sentry/src/Listener/SetRedisEventEnableListener.php deleted file mode 100644 index 14608ab72..000000000 --- a/src/sentry/src/Listener/SetRedisEventEnableListener.php +++ /dev/null @@ -1,41 +0,0 @@ -config->has('redis')) { - return; - } - - foreach ($this->config->get('redis', []) as $pool => $_) { - $this->config->set("redis.{$pool}.event.enable", true); - } - } -} diff --git a/src/sentry/src/Listener/SetRequestLifecycleListener.php b/src/sentry/src/Listener/SetRequestLifecycleListener.php deleted file mode 100644 index 680f4d6f0..000000000 --- a/src/sentry/src/Listener/SetRequestLifecycleListener.php +++ /dev/null @@ -1,104 +0,0 @@ -config->has($key)) { - $this->config->set($key, true); - } - } - - if ( - ! $this->switcher->isEnable('request') - && ! $this->switcher->isTracingEnable('request') - ) { - return; - } - - $servers = $this->config->get('server.servers', []); - - foreach ($servers as &$server) { - $callbacks = $server['callbacks'] ?? []; - $handler = $callbacks[Event::ON_REQUEST][0] ?? $callbacks[Event::ON_RECEIVE][0] ?? null; - - if (! $handler) { - continue; - } - - if ( - is_a($handler, HttpServer::class, true) - || is_a($handler, RpcServer::class, true) - ) { - $server['options'] ??= []; - $server['options']['enable_request_lifecycle'] = true; - } - } - - $this->config->set('server.servers', $servers); - } -}