diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 2faaf18c..e222afc5 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -12,12 +12,12 @@ jobs: runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental == true }} strategy: + fail-fast: false matrix: php: - '7.4' - '7.3' - '7.2' - - '7.1' sentry_constraint: [false] symfony_constraint: [false] experimental: [false] @@ -30,12 +30,12 @@ jobs: php: '7.3' symfony_constraint: 4.4.* - description: 'Symfony 3.4' - php: '7.1' + php: '7.2' symfony_constraint: 3.4.* env: SYMFONY_DEPRECATIONS_HELPER: disabled - description: 'prefer lowest' - php: '7.1' + php: '7.2' composer_option: '--prefer-lowest' symfony_constraint: 3.4.* env: @@ -47,7 +47,7 @@ jobs: - uses: actions/cache@v2 with: path: ~/.composer/cache/files - key: ${{ matrix.php }}-${{ matrix.symfony_constraint }}-${{ matrix.composer_option }} + key: ${{ matrix.php }}-${{ matrix.symfony_constraint }}-${{ matrix.composer_option }} - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 46090471..f58032ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,87 +1,103 @@ # Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## Unreleased - - CLI commands registration policy changed to lazy load + +- Enable back all error listeners from base SDK integration (#322) +- Added `options.traces_sampler` and `options.traces_sample_rate` configuration options (#385) +- [BC BREAK] Removed the `options.project_root` configuration option. Instead of setting it, use a combination of `options.in_app_include` and `options.in_app_exclude` (#385) +- [BC BREAK] Removed the `options.excluded_exceptions` configuration option. Instead of setting it, configure the `IgnoreErrorsIntegration` integration (#385) +- CLI commands registration policy changed to lazy load ## 3.5.3 (2020-10-13) - - Refactors and fixes class aliases for more robustness (#315 #359, thanks to @guilliamxavier) + +- Refactors and fixes class aliases for more robustness (#315 #359, thanks to @guilliamxavier) ## 3.5.2 (2020-07-08) - - Use `jean85/pretty-package-versions` `^1.5` to leverage the new `getRootPackageVersion` method (c8799ac) - - Fix support for PHP preloading (#354, thanks to @annuh) - - Fix `capture_soft_fails: false` option for the Messenger (#353) -## 4.0.0 (TBA) - - Enable back all error listeners from base SDK integration (#322) +- Use `jean85/pretty-package-versions` `^1.5` to leverage the new `getRootPackageVersion` method (c8799ac) +- Fix support for PHP preloading (#354, thanks to @annuh) +- Fix `capture_soft_fails: false` option for the Messenger (#353) ## 3.5.1 (2020-05-07) - - Capture events using the `Hub` in the `MessengerListener` to avoid loosing `Scope` data (#339, thanks to @sh41) - - Capture multiple events if multiple exceptions are generated in a Messenger Worker context (#340, thanks to @emarref) + +- Capture events using the `Hub` in the `MessengerListener` to avoid loosing `Scope` data (#339, thanks to @sh41) +- Capture multiple events if multiple exceptions are generated in a Messenger Worker context (#340, thanks to @emarref) ## 3.5.0 (2020-05-04) - - Capture and flush messages in a Messenger Worker context (#326, thanks to @emarref) - - Support Composer 2 (#335) - - Avoid issues with dependency lower bound, fix #331 (#335) + +- Capture and flush messages in a Messenger Worker context (#326, thanks to @emarref) +- Support Composer 2 (#335) +- Avoid issues with dependency lower bound, fix #331 (#335) ## 3.4.4 (2020-03-16) - - Improve `release` option default value (#325) + +- Improve `release` option default value (#325) ## 3.4.3 (2020-02-03) - - Change default of `in_app_include` to empty, due to getsentry/sentry-php#958 (#311) - - Improve class_alias robustness (#315) + +- Change default of `in_app_include` to empty, due to getsentry/sentry-php#958 (#311) +- Improve class_alias robustness (#315) ## 3.4.2 (2020-01-29) - - Remove space from classname used with `class_alias` (#313) + +- Remove space from classname used with `class_alias` (#313) ## 3.4.1 (2020-01-24) - - Fix issue due to usage of `class_alias` to fix deprecations, which could break BC layers of third party packages (#309, thanks to @scheb) + +- Fix issue due to usage of `class_alias` to fix deprecations, which could break BC layers of third party packages (#309, thanks to @scheb) ## 3.4.0 (2020-01-20) - - Add support for `sentry/sentry` 2.3 (#298) - - Drop support for `sentry/sentry` < 2.3 (#298) - - Add support to `in_app_include` client option (#298) - - Remap `excluded_exceptions` option to use the new `IgnoreErrorsIntegration` (#298) + +- Add support for `sentry/sentry` 2.3 (#298) +- Drop support for `sentry/sentry` < 2.3 (#298) +- Add support to `in_app_include` client option (#298) +- Remap `excluded_exceptions` option to use the new `IgnoreErrorsIntegration` (#298) ## 3.3.2 (2020-01-16) - - Fix issue with exception listener under Symfony 4.3 (#301) + +- Fix issue with exception listener under Symfony 4.3 (#301) ## 3.3.1 (2020-01-14) - - Fixed Release + +- Fixed Release ## 3.3.0 (2020-01-14) - - Add support for Symfony 5.0 (#266, thanks to @Big-Shark) - - Drop support for Symfony < 3.4 (#277) - - Add default value for the `release` option, using the detected root package version (#291 #292, thanks to @Ocramius) + +- Add support for Symfony 5.0 (#266, thanks to @Big-Shark) +- Drop support for Symfony < 3.4 (#277) +- Add default value for the `release` option, using the detected root package version (#291 #292, thanks to @Ocramius) ## 3.2.1 (2019-12-19) - - Fix handling of command with no name on `ConsoleListener` (#261) - - Remove check by AuthorizationChecker in `RequestListener` (#264) - - Fixed undefined variable in `RequestListener` (#263) + +- Fix handling of command with no name on `ConsoleListener` (#261) +- Remove check by AuthorizationChecker in `RequestListener` (#264) +- Fixed undefined variable in `RequestListener` (#263) ## 3.2.0 (2019-10-04) - - Add forward compatibility with Symfony 5 (#235, thanks to @garak) - - Fix Hub initialization for `ErrorListener` (#243, thanks to @teohhanhui) - - Fix compatibility with sentry/sentry 2.2+ (#244) - - Add support for `class_serializers` option (#245) - - Add support for `max_request_body_size` option (#249) - - Add option to disable the error listener completely (#247, thanks to @HypeMC) - - Add options to register the Monolog Handler (#247, thanks to @HypeMC) + +- Add forward compatibility with Symfony 5 (#235, thanks to @garak) +- Fix Hub initialization for `ErrorListener` (#243, thanks to @teohhanhui) +- Fix compatibility with sentry/sentry 2.2+ (#244) +- Add support for `class_serializers` option (#245) +- Add support for `max_request_body_size` option (#249) +- Add option to disable the error listener completely (#247, thanks to @HypeMC) +- Add options to register the Monolog Handler (#247, thanks to @HypeMC) ## 3.1.0 (2019-07-02) - - Add support for Symfony 2.8 (#233, thanks to @nocive) - - Fix handling of ESI requests (#213, thanks to @franmomu) + +- Add support for Symfony 2.8 (#233, thanks to @nocive) +- Fix handling of ESI requests (#213, thanks to @franmomu) ## 3.0.0 (2019-05-10) - - Add the `sentry:test` command, to test if the Sentry SDK is functioning properly. + +- Add the `sentry:test` command, to test if the Sentry SDK is functioning properly. ## 3.0.0-beta2 (2019-03-22) - - Disable Sentry's ErrorHandler, and report all errors using Symfony's events (#204) + +- Disable Sentry's ErrorHandler, and report all errors using Symfony's events (#204) ## 3.0.0-beta1 (2019-03-06) + The 3.0 major release has multiple breaking changes. The most notable one is the upgrade to the 2.0 base SDK client. Refer to the [UPGRADE-3.0.md](https://github.com/getsentry/sentry-symfony/blob/master/UPGRADE-3.0.md) document for a detailed explanation. diff --git a/README.md b/README.md index 85142e07..831beceb 100644 --- a/README.md +++ b/README.md @@ -86,9 +86,6 @@ sentry: options: environment: '%kernel.environment%' release: '%env(VERSION)%' #your app version - excluded_exceptions: #exclude validation errors - - App\Exception\UserNotFoundException - - Symfony\Component\Security\Core\Exception\AccessDeniedException ``` The parameter `options` allows to fine-tune exceptions. To discover more options, please refer to diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md new file mode 100644 index 00000000..f25b3bd9 --- /dev/null +++ b/UPGRADE-4.0.md @@ -0,0 +1,27 @@ +# Upgrade 3.x to 4.0 + +- Removed the `sentry.options.excluded_exceptions` configuration option. + + Before: + + ```yaml + sentry: + options: + excluded_exceptions: + - RuntimeException + ``` + + After: + + ```yaml + sentry: + integrations: + - '@Sentry\Integration\IgnoreErrorsIntegration' + + services: + Sentry\Integration\IgnoreErrorsIntegration: + arguments: + $options: + ignore_exceptions: + - RuntimeException + ``` diff --git a/composer.json b/composer.json index bc4077d6..ce4d0251 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "require": { "php": "^7.1", "jean85/pretty-package-versions": "^1.5", - "sentry/sdk": "^2.1", + "sentry/sdk": "^3.0", "symfony/config": "^3.4||^4.0||^5.0", "symfony/console": "^3.4||^4.0||^5.0", "symfony/dependency-injection": "^3.4||^4.0||^5.0", @@ -30,14 +30,14 @@ "symfony/security-core": "^3.4||^4.0||^5.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.8", - "jangregor/phpstan-prophecy": "^0.6.2", - "monolog/monolog": "^1.11||^2.0", - "php-http/mock-client": "^1.0", + "friendsofphp/php-cs-fixer": "^2.16", + "jangregor/phpstan-prophecy": "^0.8", + "monolog/monolog": "^1.3||^2.0", + "php-http/mock-client": "^1.4", "phpspec/prophecy": "!=1.11.0", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.19", - "phpstan/phpstan-phpunit": "^0.12.8", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", "phpunit/phpunit": "^7.5||^8.5", "symfony/browser-kit": "^3.4||^4.0||^5.0", "symfony/expression-language": "^3.4||^4.0||^5.0", @@ -49,7 +49,7 @@ "symfony/yaml": "^3.4||^4.0||^5.0" }, "suggest": { - "monolog/monolog": "Required to use the Monolog handler" + "monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler." }, "autoload": { "psr-4": { @@ -62,13 +62,19 @@ } }, "scripts": { - "phpstan": "vendor/bin/phpstan analyse", - "cs-check": "vendor/bin/php-cs-fixer fix --ansi --verbose --dry-run", - "cs-fix": "vendor/bin/php-cs-fixer fix --ansi --verbose" + "tests": [ + "vendor/bin/phpunit --verbose" + ], + "phpcs": [ + "vendor/bin/php-cs-fixer fix --verbose --diff --dry-run" + ], + "phpstan": [ + "vendor/bin/phpstan analyse" + ] }, "extra": { "branch-alias": { - "master": "4.x-dev", + "dev-master": "4.x-dev", "releases/3.2.x": "3.2.x-dev", "releases/2.x": "2.x-dev", "releases/1.x": "1.x-dev" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index c4ac0cda..67f7cfd1 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -229,7 +229,6 @@ parameters: message: "#^Comparison operation \"\\>\\=\" between \\d+ and 40300 is always true\\.$#" count: 1 path: test/End2End/App/Kernel.php - - message: "#^Class Symfony\\\\Bundle\\\\FrameworkBundle\\\\Client not found\\.$#" count: 1 @@ -300,11 +299,6 @@ parameters: count: 1 path: test/EventListener/RequestListenerTest.php - - - message: "#^Method Sentry\\\\SentryBundle\\\\Test\\\\EventListener\\\\RequestListenerTest\\:\\:getUserContext\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: test/EventListener/RequestListenerTest.php - - message: "#^Method Sentry\\\\SentryBundle\\\\Test\\\\EventListener\\\\RequestListenerTest\\:\\:getTagsContext\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index e2945b27..c59149bf 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -79,9 +79,6 @@ public function getConfigTreeBuilder(): TreeBuilder '%kernel.project_dir%/vendor', ]) ->prototype('scalar'); - $optionsChildNodes->arrayNode('excluded_exceptions') - ->defaultValue([]) - ->prototype('scalar'); $optionsChildNodes->scalarNode('http_proxy'); $optionsChildNodes->arrayNode('integrations') ->prototype('scalar') @@ -109,7 +106,6 @@ public function getConfigTreeBuilder(): TreeBuilder $optionsChildNodes->arrayNode('prefixes') ->defaultValue($defaultValues->getPrefixes()) ->prototype('scalar'); - $optionsChildNodes->scalarNode('project_root'); $releaseNode = $optionsChildNodes->scalarNode('release') ->info('Release version to be reported to sentry, see https://docs.sentry.io/workflow/releases/?platform=php') @@ -126,6 +122,13 @@ public function getConfigTreeBuilder(): TreeBuilder $optionsChildNodes->arrayNode('tags') ->normalizeKeys(false) ->prototype('scalar'); + $optionsChildNodes->scalarNode('traces_sampler') + ->validate() + ->ifTrue($this->isNotAValidCallback()) + ->thenInvalid('Expecting callable or service reference, got %s'); + $optionsChildNodes->floatNode('traces_sample_rate') + ->min(0.0) + ->max(1.0); // Bundle-specific configuration $listenerPriorities = $rootNode->children() diff --git a/src/DependencyInjection/SentryExtension.php b/src/DependencyInjection/SentryExtension.php index 2c782dad..165e04c5 100644 --- a/src/DependencyInjection/SentryExtension.php +++ b/src/DependencyInjection/SentryExtension.php @@ -74,13 +74,14 @@ private function passConfigurationToOptions(ContainerBuilder $container, array $ 'max_breadcrumbs', 'max_value_length', 'prefixes', - 'project_root', 'release', 'sample_rate', 'send_attempts', 'send_default_pii', 'server_name', 'tags', + 'traces_sample_rate', + 'traces_sampler', ]; foreach ($mappableOptions as $optionName) { @@ -130,9 +131,8 @@ private function passConfigurationToOptions(ContainerBuilder $container, array $ } // we ignore fatal errors wrapped by Symfony because they produce double event reporting - $processedOptions['excluded_exceptions'][] = FatalError::class; $ignoreOptions = [ - 'ignore_exceptions' => $processedOptions['excluded_exceptions'], + 'ignore_exceptions' => [FatalError::class], ]; $integrations[] = new Definition(IgnoreErrorsIntegration::class, [$ignoreOptions]); diff --git a/src/EventListener/MessengerListener.php b/src/EventListener/MessengerListener.php index 4391e371..81e59829 100644 --- a/src/EventListener/MessengerListener.php +++ b/src/EventListener/MessengerListener.php @@ -2,7 +2,6 @@ namespace Sentry\SentryBundle\EventListener; -use Sentry\FlushableClientInterface; use Sentry\State\HubInterface; use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent; use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent; @@ -66,7 +65,7 @@ public function onWorkerMessageHandled(WorkerMessageHandledEvent $event): void private function flush(): void { $client = $this->hub->getClient(); - if ($client instanceof FlushableClientInterface) { + if (null !== $client) { $client->flush(); } } diff --git a/src/EventListener/RequestListener.php b/src/EventListener/RequestListener.php index f9bc0c71..13730717 100644 --- a/src/EventListener/RequestListener.php +++ b/src/EventListener/RequestListener.php @@ -90,7 +90,7 @@ public function onKernelRequest(RequestListenerRequestEvent $event): void SentrySdk::getCurrentHub() ->configureScope(function (Scope $scope) use ($userData): void { - $scope->setUser($userData, true); + $scope->setUser($userData); }); } diff --git a/test/BaseTestCase.php b/test/BaseTestCase.php index bf531286..ae03af64 100644 --- a/test/BaseTestCase.php +++ b/test/BaseTestCase.php @@ -13,7 +13,7 @@ abstract class BaseTestCase extends TestCase { protected function getSupportedOptionsCount(): int { - return 26; + return 27; } protected function createRequestEvent(Request $request = null, int $type = KernelInterface::MASTER_REQUEST) diff --git a/test/Command/SentryTestCommandTest.php b/test/Command/SentryTestCommandTest.php index 08ced888..b37d8aff 100644 --- a/test/Command/SentryTestCommandTest.php +++ b/test/Command/SentryTestCommandTest.php @@ -4,6 +4,7 @@ use Prophecy\Argument; use Sentry\ClientInterface; +use Sentry\EventId; use Sentry\Options; use Sentry\SentryBundle\Command\SentryTestCommand; use Sentry\SentryBundle\Test\BaseTestCase; @@ -24,7 +25,7 @@ public function testExecuteSuccessfully(): void $hub = $this->prophesize(HubInterface::class); $hub->getClient() ->willReturn($client->reveal()); - $lastEventId = 'abcdef0123456'; + $lastEventId = EventId::generate(); $hub->captureMessage(Argument::containingString('test'), Argument::cetera()) ->shouldBeCalled() ->willReturn($lastEventId); diff --git a/test/DependencyInjection/ConfigurationTest.php b/test/DependencyInjection/ConfigurationTest.php index 2f3027ee..d1d9666a 100644 --- a/test/DependencyInjection/ConfigurationTest.php +++ b/test/DependencyInjection/ConfigurationTest.php @@ -17,10 +17,8 @@ public function testDataProviderIsMappingTheRightNumberOfOptions(): void $providerData = $this->optionValuesProvider(); $supportedOptions = \array_unique(\array_column($providerData, 0)); - $expectedCount = $this->getSupportedOptionsCount() + 1; - $this->assertCount( - $expectedCount, + $this->getSupportedOptionsCount(), $supportedOptions, 'Provider for configuration options mismatch: ' . PHP_EOL . print_r($supportedOptions, true) ); @@ -62,7 +60,6 @@ public function testConfigurationDefaults(): void '%kernel.project_dir%/vendor', ], 'integrations' => [], - 'excluded_exceptions' => [], 'prefixes' => $defaultSdkValues->getPrefixes(), 'tags' => [], 'release' => PrettyVersions::getVersion('sentry/sentry-symfony')->getPrettyVersion(), @@ -116,7 +113,6 @@ public function optionValuesProvider(): array ['in_app_include', ['some/path']], ['in_app_exclude', ['some/path']], ['integrations', []], - ['excluded_exceptions', [\Throwable::class]], ['logger', 'some-logger'], ['max_breadcrumbs', 15], ['max_request_body_size', 'none'], @@ -125,7 +121,6 @@ public function optionValuesProvider(): array ['max_request_body_size', 'always'], ['max_value_length', 1000], ['prefixes', ['some-string']], - ['project_root', '/some/dir'], ['release', 'abc0123'], ['sample_rate', 0], ['sample_rate', 1], @@ -134,6 +129,9 @@ public function optionValuesProvider(): array ['send_default_pii', true], ['server_name', 'server001.example.com'], ['tags', ['tag-name' => 'value']], + ['traces_sample_rate', 0], + ['traces_sample_rate', 1], + ['traces_sampler', 'count'], ]; } @@ -151,7 +149,7 @@ public function testInvalidValues(string $option, $value): void public function invalidValuesProvider(): array { - $values = [ + return [ ['attach_stacktrace', 'string'], ['before_breadcrumb', 'this is not a callable'], ['before_breadcrumb', [$this, 'is not a callable']], @@ -161,6 +159,7 @@ public function invalidValuesProvider(): array ['before_send', [$this, 'is not a callable']], ['before_send', false], ['before_send', -1], + ['capture_silenced_errors', 'string'], ['class_serializers', 'this is not a callable'], ['class_serializers', [$this, 'is not a callable']], ['class_serializers', false], @@ -173,7 +172,6 @@ public function invalidValuesProvider(): array ['enable_compression', 'string'], ['environment', ''], ['error_types', []], - ['excluded_exceptions', 'some-string'], ['http_proxy', []], ['in_app_include', 'some/single/path'], ['in_app_exclude', 'some/single/path'], @@ -187,7 +185,6 @@ public function invalidValuesProvider(): array ['max_value_length', -1], ['max_value_length', []], ['prefixes', 'string'], - ['project_root', []], ['release', []], ['sample_rate', 1.1], ['sample_rate', -1], @@ -197,9 +194,13 @@ public function invalidValuesProvider(): array ['send_default_pii', 'false'], ['server_name', []], ['tags', 'invalid-unmapped-tag'], + ['traces_sample_rate', -1], + ['traces_sample_rate', 1.1], + ['traces_sampler', 'this is not a callable'], + ['traces_sampler', [$this, 'is not a callable']], + ['traces_sampler', false], + ['traces_sampler', -1], ]; - - return $values; } private function processConfiguration(array $values): array diff --git a/test/DependencyInjection/SentryExtensionTest.php b/test/DependencyInjection/SentryExtensionTest.php index b84efb6a..3f4750b6 100644 --- a/test/DependencyInjection/SentryExtensionTest.php +++ b/test/DependencyInjection/SentryExtensionTest.php @@ -2,12 +2,15 @@ namespace Sentry\SentryBundle\Test\DependencyInjection; -use Jean85\PrettyVersions; +use GuzzleHttp\Promise\FulfilledPromise; +use GuzzleHttp\Promise\PromiseInterface; use Monolog\Logger as MonologLogger; use Prophecy\Argument; use Sentry\Breadcrumb; use Sentry\ClientInterface; use Sentry\Event; +use Sentry\EventHint; +use Sentry\EventId; use Sentry\Integration\IntegrationInterface; use Sentry\Monolog\Handler; use Sentry\Options; @@ -39,12 +42,7 @@ public function testDataProviderIsMappingTheRightNumberOfOptions(): void $supportedOptions = \array_unique(\array_column($providerData, 0)); // subtracted one is `integration`, which cannot be tested with the provider - $expectedCount = $this->getSupportedOptionsCount(); - --$expectedCount; // excluded_exceptions is remapped to the new IgnoreErrorsIntegration - - if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() === '2.0.0') { - --$expectedCount; - } + $expectedCount = $this->getSupportedOptionsCount() - 1; $this->assertCount( $expectedCount, @@ -117,7 +115,7 @@ public function testValuesArePassedToOptions(string $name, $value, string $gette public function optionsValueProvider(): array { - $options = [ + return [ ['attach_stacktrace', true, 'shouldAttachStacktrace'], ['before_breadcrumb', __NAMESPACE__ . '\mockBeforeBreadcrumb', 'getBeforeBreadcrumbCallback'], ['before_send', __NAMESPACE__ . '\mockBeforeSend', 'getBeforeSendCallback'], @@ -141,20 +139,16 @@ public function optionsValueProvider(): array ['max_request_body_size', 'always'], ['max_value_length', 1000], ['prefixes', ['/some/path/prefix/']], - ['project_root', '/some/project/'], ['release', 'abc0123'], ['sample_rate', 0.5], ['send_attempts', 2], ['send_default_pii', true, 'shouldSendDefaultPii'], ['server_name', 'server.example.com'], ['tags', ['tag-name' => 'tag-value']], + ['traces_sample_rate', 0.5], + ['traces_sampler', __NAMESPACE__ . '\mockTracesSampler'], + ['capture_silenced_errors', true, 'shouldCaptureSilencedErrors'], ]; - - if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() !== '2.0.0') { - $options[] = ['capture_silenced_errors', true, 'shouldCaptureSilencedErrors']; - } - - return $options; } public function testErrorTypesAreParsed(): void @@ -333,6 +327,7 @@ public function testIntegrations(): void ]); $integrations = $this->getOptionsFrom($container)->getIntegrations(); + $this->assertIsArray($integrations); $this->assertNotEmpty($integrations); $found = false; @@ -510,6 +505,11 @@ function mockClassSerializer($object) return ['value' => 'serialized_class']; } +function mockTracesSampler(): float +{ + return 0; +} + class CallbackMock { public static function callback() @@ -537,22 +537,22 @@ public function getOptions(): Options return new Options(); } - public function captureMessage(string $message, ?Severity $level = null, ?Scope $scope = null): ?string + public function captureMessage(string $message, ?Severity $level = null, ?Scope $scope = null): ?EventId { return null; } - public function captureException(\Throwable $exception, ?Scope $scope = null): ?string + public function captureException(\Throwable $exception, ?Scope $scope = null): ?EventId { return null; } - public function captureLastError(?Scope $scope = null): ?string + public function captureLastError(?Scope $scope = null): ?EventId { return null; } - public function captureEvent(array $payload, ?Scope $scope = null): ?string + public function captureEvent(Event $event, ?EventHint $hint = null, ?Scope $scope = null): ?EventId { return null; } @@ -561,4 +561,9 @@ public function getIntegration(string $className): ?IntegrationInterface { return null; } + + public function flush(?int $timeout = null): PromiseInterface + { + return new FulfilledPromise(true); + } } diff --git a/test/End2End/End2EndTest.php b/test/End2End/End2EndTest.php index f30e2ef6..abb0b5ff 100644 --- a/test/End2End/End2EndTest.php +++ b/test/End2End/End2EndTest.php @@ -129,6 +129,9 @@ public function testGet500(): void $this->assertEventCount(1); } + /** + * @requires PHP >= 7.3 + */ public function testGetFatal(): void { $client = static::createClient(); diff --git a/test/End2End/StubTransportFactory.php b/test/End2End/StubTransportFactory.php index 0e375505..961db399 100644 --- a/test/End2End/StubTransportFactory.php +++ b/test/End2End/StubTransportFactory.php @@ -2,8 +2,12 @@ namespace Sentry\SentryBundle\Test\End2End; +use GuzzleHttp\Promise\FulfilledPromise; +use GuzzleHttp\Promise\PromiseInterface; use Sentry\Event; use Sentry\Options; +use Sentry\Response; +use Sentry\ResponseStatus; use Sentry\Transport\TransportFactoryInterface; use Sentry\Transport\TransportInterface; @@ -14,14 +18,14 @@ class StubTransportFactory implements TransportFactoryInterface public function create(Options $options): TransportInterface { return new class() implements TransportInterface { - public function send(Event $event): ?string + public function send(Event $event): PromiseInterface { touch(End2EndTest::SENT_EVENTS_LOG); if ($event->getMessage()) { $message = $event->getMessage(); } elseif ($event->getExceptions()) { - $message = $event->getExceptions()[0]['value']; + $message = $event->getExceptions()[0]->getValue(); } else { $message = 'NO MESSAGE NOR EXCEPTIONS'; } @@ -32,7 +36,12 @@ public function send(Event $event): ?string FILE_APPEND ); - return $event->getId(); + return new FulfilledPromise(new Response(ResponseStatus::success(), $event)); + } + + public function close(?int $timeout = null): PromiseInterface + { + return new FulfilledPromise(true); } }; } diff --git a/test/EventListener/ConsoleListenerTest.php b/test/EventListener/ConsoleListenerTest.php index 1eb325f6..f246a9e1 100644 --- a/test/EventListener/ConsoleListenerTest.php +++ b/test/EventListener/ConsoleListenerTest.php @@ -79,10 +79,10 @@ public function testOnConsoleCommandWithNoCommandNameAddsPlaceholder(): void private function getTagsContext(Scope $scope): array { - $event = new Event(); - $scope->applyToEvent($event, []); + $event = Event::createEvent(); + $scope->applyToEvent($event); - return $event->getTagsContext()->toArray(); + return $event->getTags(); } private function createConsoleCommandEvent(?Command $command): ConsoleCommandEvent diff --git a/test/EventListener/MessengerListenerTest.php b/test/EventListener/MessengerListenerTest.php index 69b14f44..9d540cf1 100644 --- a/test/EventListener/MessengerListenerTest.php +++ b/test/EventListener/MessengerListenerTest.php @@ -2,7 +2,8 @@ namespace Sentry\SentryBundle\Test\EventListener; -use Sentry\FlushableClientInterface; +use Sentry\ClientInterface; +use Sentry\EventId; use Sentry\SentryBundle\EventListener\MessengerListener; use Sentry\SentryBundle\Test\BaseTestCase; use Sentry\State\HubInterface; @@ -14,16 +15,16 @@ class MessengerListenerTest extends BaseTestCase { - /** @var \Prophecy\Prophecy\ObjectProphecy|FlushableClientInterface */ + /** @var \Prophecy\Prophecy\ObjectProphecy */ private $client; - /** @var \Prophecy\Prophecy\ObjectProphecy|HubInterface */ + /** @var \Prophecy\Prophecy\ObjectProphecy */ private $hub; protected function setUp(): void { parent::setUp(); - $this->client = $this->prophesize(FlushableClientInterface::class); + $this->client = $this->prophesize(ClientInterface::class); $this->hub = $this->prophesize(HubInterface::class); $this->hub->getClient()->willReturn($this->client); } @@ -40,7 +41,7 @@ public function testSoftFailsAreRecorded(): void $error = new \RuntimeException(); $wrappedError = new HandlerFailedException($envelope, [$error]); - $this->hub->captureException($error)->shouldBeCalled(); + $this->hub->captureException($error)->shouldBeCalled()->willReturn(EventId::generate()); $this->client->flush()->shouldBeCalled(); $listener = new MessengerListener($this->hub->reveal(), true); @@ -60,7 +61,7 @@ public function testNonMessengerErrorsAreRecorded(): void $error = new \RuntimeException(); - $this->hub->captureException($error)->shouldBeCalled(); + $this->hub->captureException($error)->shouldBeCalled()->willReturn(EventId::generate()); $this->client->flush()->shouldBeCalled(); $listener = new MessengerListener($this->hub->reveal(), true); @@ -81,7 +82,7 @@ public function testHardFailsAreRecorded(): void $error = new \RuntimeException(); $wrappedError = new HandlerFailedException($envelope, [$error]); - $this->hub->captureException($error)->shouldBeCalled(); + $this->hub->captureException($error)->shouldBeCalled()->willReturn(EventId::generate()); $this->client->flush()->shouldBeCalled(); $listener = new MessengerListener($this->hub->reveal(), true); @@ -123,7 +124,7 @@ public function testHardFailsAreRecordedWithCaptureSoftDisabled(): void $error = new \RuntimeException(); $wrappedError = new HandlerFailedException($envelope, [$error]); - $this->hub->captureException($error)->shouldBeCalled(); + $this->hub->captureException($error)->shouldBeCalled()->willReturn(EventId::generate()); $this->client->flush()->shouldBeCalled(); $listener = new MessengerListener($this->hub->reveal(), false); @@ -146,8 +147,8 @@ public function testHandlerFailedExceptionIsUnwrapped(): void $event = $this->getMessageFailedEvent($envelope, 'receiver', $wrappedError, false); - $this->hub->captureException($error1)->shouldBeCalled(); - $this->hub->captureException($error2)->shouldBeCalled(); + $this->hub->captureException($error1)->shouldBeCalled()->willReturn(EventId::generate()); + $this->hub->captureException($error2)->shouldBeCalled()->willReturn(EventId::generate()); $this->client->flush()->shouldBeCalled(); $listener = new MessengerListener($this->hub->reveal()); diff --git a/test/EventListener/RequestListenerTest.php b/test/EventListener/RequestListenerTest.php index e6577c55..428de10a 100644 --- a/test/EventListener/RequestListenerTest.php +++ b/test/EventListener/RequestListenerTest.php @@ -11,6 +11,7 @@ use Sentry\SentrySdk; use Sentry\State\HubInterface; use Sentry\State\Scope; +use Sentry\UserDataBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\ControllerEvent; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; @@ -81,10 +82,10 @@ public function testOnKernelRequestUserDataIsSetToScope($user): void $listener->onKernelRequest($event); - $expectedUserData = [ + $expectedUserData = UserDataBag::createFromArray([ 'ip_address' => '1.2.3.4', 'username' => 'john-doe', - ]; + ]); $this->assertEquals($expectedUserData, $this->getUserContext($this->currentScope)); } @@ -112,7 +113,7 @@ public function testOnKernelRequestUserDataIsNotSetIfSendPiiIsDisabled(): void $listener->onKernelRequest($event); - $this->assertEquals([], $this->getUserContext($this->currentScope)); + $this->assertNull($this->getUserContext($this->currentScope)); } public function testOnKernelRequestUserDataIsNotSetIfNoClientIsPresent(): void @@ -132,7 +133,7 @@ public function testOnKernelRequestUserDataIsNotSetIfNoClientIsPresent(): void $listener->onKernelRequest($event); - $this->assertEquals([], $this->getUserContext($this->currentScope)); + $this->assertNull($this->getUserContext($this->currentScope)); } public function testOnKernelRequestUsernameIsNotSetIfTokenStorageIsAbsent(): void @@ -150,9 +151,9 @@ public function testOnKernelRequestUsernameIsNotSetIfTokenStorageIsAbsent(): voi $listener->onKernelRequest($event); - $expectedUserData = [ + $expectedUserData = UserDataBag::createFromArray([ 'ip_address' => '1.2.3.4', - ]; + ]); $this->assertEquals($expectedUserData, $this->getUserContext($this->currentScope)); } @@ -175,9 +176,9 @@ public function testOnKernelRequestUsernameIsNotSetIfTokenIsAbsent(): void $listener->onKernelRequest($event); - $expectedUserData = [ + $expectedUserData = UserDataBag::createFromArray([ 'ip_address' => '1.2.3.4', - ]; + ]); $this->assertEquals($expectedUserData, $this->getUserContext($this->currentScope)); } @@ -207,9 +208,9 @@ public function testOnKernelRequestUsernameIsNotSetIfTokenIsNotAuthenticated(): $listener->onKernelRequest($event); - $expectedUserData = [ + $expectedUserData = UserDataBag::createFromArray([ 'ip_address' => '1.2.3.4', - ]; + ]); $this->assertEquals($expectedUserData, $this->getUserContext($this->currentScope)); } @@ -232,9 +233,9 @@ public function testOnKernelRequestUsernameIsNotSetIfUserIsNotRemembered(): void $listener->onKernelRequest($event); - $expectedUserData = [ + $expectedUserData = UserDataBag::createFromArray([ 'ip_address' => '1.2.3.4', - ]; + ]); $this->assertEquals($expectedUserData, $this->getUserContext($this->currentScope)); } @@ -291,20 +292,20 @@ public function testOnKernelRequestUserDataAndTagsAreNotSetInSubRequest(): void $this->assertEmpty($this->getTagsContext($this->currentScope)); } - private function getUserContext(Scope $scope): array + private function getUserContext(Scope $scope): ?UserDataBag { - $event = new Event(); - $scope->applyToEvent($event, []); + $event = Event::createEvent(); + $scope->applyToEvent($event); - return $event->getUserContext()->toArray(); + return $event->getUser(); } private function getTagsContext(Scope $scope): array { - $event = new Event(); - $scope->applyToEvent($event, []); + $event = Event::createEvent(); + $scope->applyToEvent($event); - return $event->getTagsContext()->toArray(); + return $event->getTags(); } private function createControllerEvent(Request $request)