From 857ee173c931dc93dd34133fc24c8dd759a2e4b7 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Mon, 12 Dec 2022 00:26:37 +0100 Subject: [PATCH] Add error handler integrations option --- CHANGELOG.md | 2 + phpstan-baseline.neon | 5 +++ src/Integration/IntegrationRegistry.php | 22 +++++----- src/Options.php | 24 ++++++++++ tests/Integration/IntegrationRegistryTest.php | 40 +++++++++++++++++ tests/OptionsTest.php | 44 +++++++++++++++++++ 6 files changed, 126 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 719f1934b..bc5f3cb7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- feat: Add `error_handler_integrations` option (#1439) + ## 3.12.0 (2022-11-22) - feat: Add `before_send_transaction` option (#1424) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 11c0ed88c..3e7f0ef55 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -240,6 +240,11 @@ parameters: count: 1 path: src/Options.php + - + message: "#^Method Sentry\\\\Options\\:\\:hasErrorHandlerIntegrations\\(\\) should return bool but returns mixed\\.$#" + count: 1 + path: src/Options.php + - message: "#^Method Sentry\\\\Options\\:\\:isCompressionEnabled\\(\\) should return bool but returns mixed\\.$#" count: 1 diff --git a/src/Integration/IntegrationRegistry.php b/src/Integration/IntegrationRegistry.php index 2c33c83ad..61b7f818f 100644 --- a/src/Integration/IntegrationRegistry.php +++ b/src/Integration/IntegrationRegistry.php @@ -122,19 +122,19 @@ private function getIntegrationsToSetup(Options $options): array */ private function getDefaultIntegrations(Options $options): array { - if (!$options->hasDefaultIntegrations()) { - return []; - } + $integrations = []; - $integrations = [ - new RequestIntegration(), - new TransactionIntegration(), - new FrameContextifierIntegration(), - new EnvironmentIntegration(), - new ModulesIntegration(), - ]; + if ($options->hasDefaultIntegrations()) { + $integrations = [ + new RequestIntegration(), + new TransactionIntegration(), + new FrameContextifierIntegration(), + new EnvironmentIntegration(), + new ModulesIntegration(), + ]; + } - if (null !== $options->getDsn()) { + if ($options->hasErrorHandlerIntegrations() && null !== $options->getDsn()) { array_unshift($integrations, new ExceptionListenerIntegration(), new ErrorListenerIntegration(), new FatalErrorListenerIntegration()); } diff --git a/src/Options.php b/src/Options.php index 1c70186da..6f7828176 100644 --- a/src/Options.php +++ b/src/Options.php @@ -608,6 +608,28 @@ public function setDefaultIntegrations(bool $enable): void $this->options = $this->resolver->resolve($options); } + /** + * Returns whether the error handler integrations are enabled or fallbacks + * to whether the default integrations are enabled when null. + */ + public function hasErrorHandlerIntegrations(): bool + { + return $this->options['error_handler_integrations'] ?? $this->hasDefaultIntegrations(); + } + + /** + * Sets whether the error handler integrations are enabled. + * + * @param ?bool $enable Flag indicating whether the error handler integrations should be enabled, fallbacks + * to "default_integrations" when null + */ + public function setErrorHandlerIntegrations(?bool $enable): void + { + $options = array_merge($this->options, ['error_handler_integrations' => $enable]); + + $this->options = $this->resolver->resolve($options); + } + /** * Gets the max length for values in the event payload. */ @@ -811,6 +833,7 @@ private function configureOptions(OptionsResolver $resolver): void $resolver->setDefaults([ 'integrations' => [], 'default_integrations' => true, + 'error_handler_integrations' => null, 'send_attempts' => 0, 'prefixes' => array_filter(explode(\PATH_SEPARATOR, get_include_path() ?: '')), 'sample_rate' => 1, @@ -874,6 +897,7 @@ private function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedTypes('integrations', ['Sentry\\Integration\\IntegrationInterface[]', 'callable']); $resolver->setAllowedTypes('send_default_pii', 'bool'); $resolver->setAllowedTypes('default_integrations', 'bool'); + $resolver->setAllowedTypes('error_handler_integrations', ['bool', 'null']); $resolver->setAllowedTypes('max_value_length', 'int'); $resolver->setAllowedTypes('http_proxy', ['null', 'string']); $resolver->setAllowedTypes('http_connect_timeout', ['int', 'float']); diff --git a/tests/Integration/IntegrationRegistryTest.php b/tests/Integration/IntegrationRegistryTest.php index e4ad5d5f2..bfad27b93 100644 --- a/tests/Integration/IntegrationRegistryTest.php +++ b/tests/Integration/IntegrationRegistryTest.php @@ -298,6 +298,46 @@ public function setupOnce(): void ModulesIntegration::class => new ModulesIntegration(), ], ]; + + yield 'Default integrations and no error handler integrations' => [ + new Options([ + 'dsn' => 'http://public@example.com/sentry/1', + 'default_integrations' => true, + 'error_handler_integrations' => false, + ]), + [ + 'The "Sentry\\Integration\\RequestIntegration" integration has been installed.', + 'The "Sentry\\Integration\\TransactionIntegration" integration has been installed.', + 'The "Sentry\\Integration\\FrameContextifierIntegration" integration has been installed.', + 'The "Sentry\\Integration\\EnvironmentIntegration" integration has been installed.', + 'The "Sentry\\Integration\\ModulesIntegration" integration has been installed.', + ], + [ + RequestIntegration::class => new RequestIntegration(), + TransactionIntegration::class => new TransactionIntegration(), + FrameContextifierIntegration::class => new FrameContextifierIntegration(), + EnvironmentIntegration::class => new EnvironmentIntegration(), + ModulesIntegration::class => new ModulesIntegration(), + ], + ]; + + yield 'No default integrations and error handler integrations' => [ + new Options([ + 'dsn' => 'http://public@example.com/sentry/1', + 'default_integrations' => false, + 'error_handler_integrations' => true, + ]), + [ + 'The "Sentry\\Integration\\ExceptionListenerIntegration" integration has been installed.', + 'The "Sentry\\Integration\\ErrorListenerIntegration" integration has been installed.', + 'The "Sentry\\Integration\\FatalErrorListenerIntegration" integration has been installed.', + ], + [ + ExceptionListenerIntegration::class => new ExceptionListenerIntegration(), + ErrorListenerIntegration::class => new ErrorListenerIntegration(), + FatalErrorListenerIntegration::class => new FatalErrorListenerIntegration(), + ], + ]; } /** diff --git a/tests/OptionsTest.php b/tests/OptionsTest.php index 85b6aed04..0202268e5 100644 --- a/tests/OptionsTest.php +++ b/tests/OptionsTest.php @@ -364,6 +364,50 @@ static function (): void {}, null, null, ]; + + yield [ + 'default_integrations', + false, + 'hasDefaultIntegrations', + 'setDefaultIntegrations', + null, + null, + ]; + + yield [ + 'error_handler_integrations', + true, + 'hasErrorHandlerIntegrations', + 'setErrorHandlerIntegrations', + null, + null, + ]; + } + + /** + * @dataProvider errorHandlerIntegrationsOptionDataProvider + */ + public function testErrorHandlerIntegrationsFallback( + bool $defaultIntegrationsValue, + ?bool $errorHandlerIntegrationsValue, + bool $expectedValue + ): void { + $options = new Options([ + 'default_integrations' => $defaultIntegrationsValue, + 'error_handler_integrations' => $errorHandlerIntegrationsValue, + ]); + + $this->assertEquals($expectedValue, $options->hasErrorHandlerIntegrations()); + } + + public function errorHandlerIntegrationsOptionDataProvider(): iterable + { + yield [true, null, true]; + yield [true, false, false]; + yield [true, true, true]; + yield [false, null, false]; + yield [false, false, false]; + yield [false, true, true]; } /**