diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yml similarity index 70% rename from .github/workflows/ci.yaml rename to .github/workflows/ci.yml index 3f4c257a5..dd0dfd160 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yml @@ -23,6 +23,7 @@ jobs: - '7.4' - '8.0' - '8.1' + - '8.2' dependencies: - lowest - highest @@ -55,23 +56,29 @@ jobs: - name: Install highest dependencies run: composer update --no-progress --no-interaction --prefer-dist - if: ${{ matrix.dependencies == 'highest' }} + if: ${{ matrix.dependencies == 'highest' && matrix.php != '8.2' }} - - name: Restrict lowest Symfony version on PHP 8.1 + - name: Install highest PHP 8.2 dependencies + run: composer update --no-progress --no-interaction --prefer-dist --ignore-platform-req=php + if: ${{ matrix.dependencies == 'highest' && matrix.php == '8.2' }} + + - name: Restrict lowest Symfony version on PHP 8.1 & 8.2 run: composer require symfony/options-resolver:^4.4.30 --no-update - if: ${{ matrix.dependencies == 'lowest' && matrix.php == '8.1' }} + if: ${{ matrix.dependencies == 'lowest' && matrix.php == '8.1' || matrix.php == '8.2' }} - name: Install lowest dependencies run: composer update --no-progress --no-interaction --prefer-dist --prefer-lowest - if: ${{ matrix.dependencies == 'lowest' }} + if: ${{ matrix.dependencies == 'lowest' && matrix.php != '8.2' }} + + - name: Install lowest PHP 8.2 dependencies + run: composer update --no-progress --no-interaction --prefer-dist --prefer-lowest --ignore-platform-req=php + if: ${{ matrix.dependencies == 'lowest' && matrix.php == '8.2' }} - name: Run tests - run: vendor/bin/phpunit --coverage-clover=build/coverage-report.xml + run: vendor/bin/phpunit --coverage-clover=coverage.xml - name: Upload code coverage - uses: codecov/codecov-action@v1 - with: - file: build/coverage-report.xml + uses: codecov/codecov-action@v3 - name: Check benchmarks run: vendor/bin/phpbench run --revs=1 --iterations=1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e0161a60..657621c4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +## 3.8.0 (2022-09-05) + +- Add `Sentry\Monolog\BreadcrumbHandler`, a Monolog handler to allow registration of logs as breadcrumbs (#1199) +- Do not setup any error handlers if the DSN is null (#1349) +- Add setter for type on the `ExceptionDataBag` (#1347) +- Drop symfony/polyfill-uuid in favour of a standalone implementation (#1346) + ## 3.7.0 (2022-07-18) - Fix `Scope::getTransaction()` so that it returns also unsampled transactions (#1334) diff --git a/composer.json b/composer.json index f6ffb3e4c..6044898ab 100644 --- a/composer.json +++ b/composer.json @@ -35,8 +35,7 @@ "psr/http-message-implementation": "^1.0", "psr/log": "^1.0|^2.0|^3.0", "symfony/options-resolver": "^3.4.43|^4.4.30|^5.0.11|^6.0", - "symfony/polyfill-php80": "^1.17", - "symfony/polyfill-uuid": "^1.13.1" + "symfony/polyfill-php80": "^1.17" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.19|3.4.*", @@ -96,7 +95,7 @@ "prefer-stable": true, "extra": { "branch-alias": { - "dev-master": "3.7.x-dev" + "dev-master": "3.8.x-dev" } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 62ea23ef5..83ea011fa 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -16,27 +16,27 @@ parameters: path: src/ClientInterface.php - - message: "#^Offset 'host' does not exist on array\\{scheme\\: 'http'\\|'https', host\\?\\: string, port\\?\\: int, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" + message: "#^Offset 'host' does not exist on array\\{scheme\\: 'http'\\|'https', host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" count: 1 path: src/Dsn.php - - message: "#^Offset 'host'\\|'path'\\|'scheme'\\|'user' on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\} in isset\\(\\) always exists and is not nullable\\.$#" + message: "#^Offset 'host'\\|'path'\\|'scheme'\\|'user' on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\} in isset\\(\\) always exists and is not nullable\\.$#" count: 1 path: src/Dsn.php - - message: "#^Offset 'path' does not exist on array\\{scheme\\: 'http'\\|'https', host\\?\\: string, port\\?\\: int, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" + message: "#^Offset 'path' does not exist on array\\{scheme\\: 'http'\\|'https', host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" count: 4 path: src/Dsn.php - - message: "#^Offset 'scheme' does not exist on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" + message: "#^Offset 'scheme' does not exist on array\\{scheme\\?\\: string, host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" count: 1 path: src/Dsn.php - - message: "#^Offset 'user' does not exist on array\\{scheme\\: 'http'\\|'https', host\\?\\: string, port\\?\\: int, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" + message: "#^Offset 'user' does not exist on array\\{scheme\\: 'http'\\|'https', host\\?\\: string, port\\?\\: int\\<0, 65535\\>, user\\?\\: string, pass\\?\\: string, path\\?\\: string, query\\?\\: string, fragment\\?\\: string\\}\\.$#" count: 1 path: src/Dsn.php @@ -95,6 +95,11 @@ parameters: count: 1 path: src/Integration/RequestIntegration.php + - + message: "#^Parameter \\#1 \\$level of method Monolog\\\\Handler\\\\AbstractHandler\\:\\:__construct\\(\\) expects 100\\|200\\|250\\|300\\|400\\|500\\|550\\|600\\|'ALERT'\\|'alert'\\|'CRITICAL'\\|'critical'\\|'DEBUG'\\|'debug'\\|'EMERGENCY'\\|'emergency'\\|'ERROR'\\|'error'\\|'INFO'\\|'info'\\|'NOTICE'\\|'notice'\\|'WARNING'\\|'warning'\\|Monolog\\\\Level, int\\|Monolog\\\\Level\\|string given\\.$#" + count: 1 + path: src/Monolog/BreadcrumbHandler.php + - message: "#^Method Sentry\\\\Options\\:\\:getBeforeBreadcrumbCallback\\(\\) should return callable\\(Sentry\\\\Breadcrumb\\)\\: Sentry\\\\Breadcrumb\\|null but returns mixed\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 814952ffa..93bf65e2c 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + $parsedDsn['host'] @@ -22,6 +22,21 @@ $userIntegrations + + + $record['channel'] + $record['level'] + $record['level'] + $record['message'] + + + getTimestamp + + + Level|int + int|string|Level|LogLevel::* + + CompatibilityProcessingHandlerTrait @@ -80,32 +95,4 @@ startTransaction - - - $name - , - , - , - , - , - , - , - , - , - Level - case - - - - - \DateTimeImmutable - - - - - : - => - } - - diff --git a/src/EventId.php b/src/EventId.php index 76c36b272..e88de486c 100644 --- a/src/EventId.php +++ b/src/EventId.php @@ -4,6 +4,8 @@ namespace Sentry; +use Sentry\Util\SentryUid; + /** * This class represents an event ID. * @@ -32,10 +34,12 @@ public function __construct(string $value) /** * Generates a new event ID. + * + * @copyright Matt Farina MIT License https://github.com/lootils/uuid/blob/master/LICENSE */ public static function generate(): self { - return new self(str_replace('-', '', uuid_create(UUID_TYPE_RANDOM))); + return new self(SentryUid::generate()); } public function __toString(): string diff --git a/src/ExceptionDataBag.php b/src/ExceptionDataBag.php index 0173e3a61..e93b6c617 100644 --- a/src/ExceptionDataBag.php +++ b/src/ExceptionDataBag.php @@ -13,7 +13,7 @@ final class ExceptionDataBag { /** - * @var class-string<\Throwable> The type of exception, e.g. RuntimeException + * @var string The type of exception, e.g. RuntimeException */ private $type; @@ -42,14 +42,22 @@ public function __construct(\Throwable $exception, ?Stacktrace $stacktrace = nul /** * Gets the type of exception, e.g. RuntimeException. - * - * @return class-string<\Throwable> */ public function getType(): string { return $this->type; } + /** + * Sets the type of the exception. + * + * @param string $type The exception type + */ + public function setType(string $type): void + { + $this->type = $type; + } + /** * Gets the value of the exception. */ diff --git a/src/Integration/IntegrationRegistry.php b/src/Integration/IntegrationRegistry.php index ff15b2b60..f117c43f1 100644 --- a/src/Integration/IntegrationRegistry.php +++ b/src/Integration/IntegrationRegistry.php @@ -126,14 +126,17 @@ private function getDefaultIntegrations(Options $options): array return []; } - return [ - new ExceptionListenerIntegration(), - new ErrorListenerIntegration(), - new FatalErrorListenerIntegration(), + $integrations = [ new RequestIntegration(), new TransactionIntegration(), new FrameContextifierIntegration(), new EnvironmentIntegration(), ]; + + if (null !== $options->getDsn()) { + array_unshift($integrations, new ExceptionListenerIntegration(), new ErrorListenerIntegration(), new FatalErrorListenerIntegration()); + } + + return $integrations; } } diff --git a/src/Monolog/BreadcrumbHandler.php b/src/Monolog/BreadcrumbHandler.php new file mode 100644 index 000000000..8c5e03b0a --- /dev/null +++ b/src/Monolog/BreadcrumbHandler.php @@ -0,0 +1,101 @@ +hub = $hub; + + parent::__construct($level, $bubble); + } + + /** + * @psalm-suppress MoreSpecificImplementedParamType + * + * @param LogRecord|array{ + * level: int, + * channel: string, + * datetime: \DateTimeImmutable, + * message: string, + * extra?: array + * } $record {@see https://github.com/Seldaek/monolog/blob/main/doc/message-structure.md} + */ + protected function write($record): void + { + $breadcrumb = new Breadcrumb( + $this->getBreadcrumbLevel($record['level']), + $this->getBreadcrumbType($record['level']), + $record['channel'], + $record['message'], + ($record['context'] ?? []) + ($record['extra'] ?? []), + $record['datetime']->getTimestamp() + ); + + $this->hub->addBreadcrumb($breadcrumb); + } + + /** + * @param Level|int $level + */ + private function getBreadcrumbLevel($level): string + { + if ($level instanceof Level) { + $level = $level->value; + } + + switch ($level) { + case Logger::DEBUG: + return Breadcrumb::LEVEL_DEBUG; + case Logger::INFO: + case Logger::NOTICE: + return Breadcrumb::LEVEL_INFO; + case Logger::WARNING: + return Breadcrumb::LEVEL_WARNING; + case Logger::ERROR: + return Breadcrumb::LEVEL_ERROR; + default: + return Breadcrumb::LEVEL_FATAL; + } + } + + private function getBreadcrumbType(int $level): string + { + if ($level >= Logger::ERROR) { + return Breadcrumb::TYPE_ERROR; + } + + return Breadcrumb::TYPE_DEFAULT; + } +} diff --git a/src/Tracing/SpanId.php b/src/Tracing/SpanId.php index d36224383..f0843681f 100644 --- a/src/Tracing/SpanId.php +++ b/src/Tracing/SpanId.php @@ -4,6 +4,8 @@ namespace Sentry\Tracing; +use Sentry\Util\SentryUid; + /** * This class represents an span ID. */ @@ -33,7 +35,7 @@ public function __construct(string $value) */ public static function generate(): self { - return new self(substr(str_replace('-', '', uuid_create(UUID_TYPE_RANDOM)), 0, 16)); + return new self(substr(SentryUid::generate(), 0, 16)); } /** diff --git a/src/Tracing/TraceId.php b/src/Tracing/TraceId.php index 2e9194757..596ec33b3 100644 --- a/src/Tracing/TraceId.php +++ b/src/Tracing/TraceId.php @@ -4,6 +4,8 @@ namespace Sentry\Tracing; +use Sentry\Util\SentryUid; + /** * This class represents an trace ID. */ @@ -33,7 +35,7 @@ public function __construct(string $value) */ public static function generate(): self { - return new self(str_replace('-', '', uuid_create(UUID_TYPE_RANDOM))); + return new self(SentryUid::generate()); } public function __toString(): string diff --git a/src/Util/SentryUid.php b/src/Util/SentryUid.php new file mode 100644 index 000000000..50c117f69 --- /dev/null +++ b/src/Util/SentryUid.php @@ -0,0 +1,42 @@ + [ new Options([ + 'dsn' => 'http://public@example.com/sentry/1', 'default_integrations' => false, ]), [], @@ -75,6 +76,7 @@ public function setupOnce(): void yield 'Default integrations and no user integrations' => [ new Options([ + 'dsn' => 'http://public@example.com/sentry/1', 'default_integrations' => true, ]), [ @@ -117,6 +119,7 @@ public function setupOnce(): void yield 'Default integrations and some user integrations' => [ new Options([ + 'dsn' => 'http://public@example.com/sentry/1', 'default_integrations' => true, 'integrations' => [ $integration1, @@ -149,6 +152,7 @@ public function setupOnce(): void yield 'Default integrations and some user integrations, one of which is also a default integration' => [ new Options([ + 'dsn' => 'http://public@example.com/sentry/1', 'default_integrations' => true, 'integrations' => [ new TransactionIntegration(), @@ -206,6 +210,7 @@ public function setupOnce(): void yield 'Default integrations and a callable as user integrations' => [ new Options([ + 'dsn' => 'http://public@example.com/sentry/1', 'default_integrations' => true, 'integrations' => static function (array $defaultIntegrations): array { return $defaultIntegrations; @@ -230,6 +235,28 @@ public function setupOnce(): void EnvironmentIntegration::class => new EnvironmentIntegration(), ], ]; + + yield 'Default integrations with DSN set to null' => [ + new Options([ + 'dsn' => null, + 'default_integrations' => true, + 'integrations' => static function (array $defaultIntegrations): array { + return $defaultIntegrations; + }, + ]), + [ + '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.', + ], + [ + RequestIntegration::class => new RequestIntegration(), + TransactionIntegration::class => new TransactionIntegration(), + FrameContextifierIntegration::class => new FrameContextifierIntegration(), + EnvironmentIntegration::class => new EnvironmentIntegration(), + ], + ]; } /** diff --git a/tests/Monolog/BreadcrumbHandlerTest.php b/tests/Monolog/BreadcrumbHandlerTest.php new file mode 100644 index 000000000..14802d951 --- /dev/null +++ b/tests/Monolog/BreadcrumbHandlerTest.php @@ -0,0 +1,88 @@ +createMock(HubInterface::class); + $hub->expects($this->once()) + ->method('addBreadcrumb') + ->with($this->callback(function (Breadcrumb $breadcrumb) use ($expectedBreadcrumb, $record): bool { + $this->assertSame($expectedBreadcrumb->getMessage(), $breadcrumb->getMessage()); + $this->assertSame($expectedBreadcrumb->getLevel(), $breadcrumb->getLevel()); + $this->assertSame($expectedBreadcrumb->getType(), $breadcrumb->getType()); + $this->assertEquals($record['datetime']->getTimestamp(), $breadcrumb->getTimestamp()); + $this->assertSame($expectedBreadcrumb->getCategory(), $breadcrumb->getCategory()); + $this->assertEquals($expectedBreadcrumb->getMetadata(), $breadcrumb->getMetadata()); + + return true; + })); + + $handler = new BreadcrumbHandler($hub); + $handler->handle($record); + } + + /** + * @return iterable, Breadcrumb}> + */ + public function handleDataProvider(): iterable + { + $defaultBreadcrumb = new Breadcrumb( + Breadcrumb::LEVEL_DEBUG, + Breadcrumb::TYPE_DEFAULT, + 'channel.foo', + 'foo bar', + [] + ); + + $levelsToBeTested = [ + Logger::DEBUG => Breadcrumb::LEVEL_DEBUG, + Logger::INFO => Breadcrumb::LEVEL_INFO, + Logger::NOTICE => Breadcrumb::LEVEL_INFO, + Logger::WARNING => Breadcrumb::LEVEL_WARNING, + ]; + + foreach ($levelsToBeTested as $loggerLevel => $breadcrumbLevel) { + yield 'with level ' . Logger::getLevelName($loggerLevel) => [ + RecordFactory::create('foo bar', $loggerLevel, 'channel.foo', [], []), + $defaultBreadcrumb->withLevel($breadcrumbLevel), + ]; + } + + yield 'with level ERROR' => [ + RecordFactory::create('foo bar', Logger::ERROR, 'channel.foo', [], []), + $defaultBreadcrumb->withLevel(Breadcrumb::LEVEL_ERROR) + ->withType(Breadcrumb::TYPE_ERROR), + ]; + + yield 'with level ALERT' => [ + RecordFactory::create('foo bar', Logger::ALERT, 'channel.foo', [], []), + $defaultBreadcrumb->withLevel(Breadcrumb::LEVEL_FATAL) + ->withType(Breadcrumb::TYPE_ERROR), + ]; + + yield 'with context' => [ + RecordFactory::create('foo bar', Logger::DEBUG, 'channel.foo', ['context' => ['foo' => 'bar']], []), + $defaultBreadcrumb->withMetadata('context', ['foo' => 'bar']), + ]; + + yield 'with extra' => [ + RecordFactory::create('foo bar', Logger::DEBUG, 'channel.foo', [], ['extra' => ['foo' => 'bar']]), + $defaultBreadcrumb->withMetadata('extra', ['foo' => 'bar']), + ]; + } +} diff --git a/tests/Monolog/RecordFactory.php b/tests/Monolog/RecordFactory.php index 9f65473db..b302c509b 100644 --- a/tests/Monolog/RecordFactory.php +++ b/tests/Monolog/RecordFactory.php @@ -40,6 +40,7 @@ public static function create(string $message, int $level, string $channel, arra 'level_name' => Logger::getLevelName($level), 'channel' => $channel, 'extra' => $extra, + 'datetime' => new \DateTimeImmutable(), ]; } } diff --git a/tests/Serializer/AbstractSerializerTest.php b/tests/Serializer/AbstractSerializerTest.php index 7d421f17e..af3e89162 100644 --- a/tests/Serializer/AbstractSerializerTest.php +++ b/tests/Serializer/AbstractSerializerTest.php @@ -538,7 +538,7 @@ public function serializationForBadStringsDataProvider(): array $utf8String = 'äöü'; return [ - [utf8_decode($utf8String), $utf8String, 'ISO-8859-1, ASCII, UTF-8'], + [mb_convert_encoding($utf8String, 'ISO-8859-1', 'UTF-8'), $utf8String, 'ISO-8859-1, ASCII, UTF-8'], ["\xC2\xA2\xC2", "\xC2\xA2\x3F"], // ill-formed 2-byte character U+00A2 (CENT SIGN) ]; } @@ -563,11 +563,7 @@ protected function invokeSerialization(AbstractSerializer $serializer, $input) } } -/** - * Class SerializerTestObject. - * - * @property mixed $keys - */ +#[\AllowDynamicProperties] class SerializerTestObject { private $foo = 'bar'; diff --git a/tests/Util/SentryUidTest.php b/tests/Util/SentryUidTest.php new file mode 100644 index 000000000..6413354d1 --- /dev/null +++ b/tests/Util/SentryUidTest.php @@ -0,0 +1,19 @@ +assertTrue($match); + } +} diff --git a/tests/phpt/error_handler_captures_errors_not_silencable_on_php_8_and_up.phpt b/tests/phpt/error_handler_captures_errors_not_silencable_on_php_8_and_up.phpt index f26fba50e..facb159b9 100644 --- a/tests/phpt/error_handler_captures_errors_not_silencable_on_php_8_and_up.phpt +++ b/tests/phpt/error_handler_captures_errors_not_silencable_on_php_8_and_up.phpt @@ -55,7 +55,13 @@ $transportFactory = new class implements TransportFactoryInterface { error_reporting(E_ALL & ~E_USER_ERROR); -$client = ClientBuilder::create(['error_types' => E_ALL, 'capture_silenced_errors' => false]) +$options = [ + 'dsn' => 'http://public@example.com/sentry/1', + 'error_types' => E_ALL, + 'capture_silenced_errors' => false, +]; + +$client = ClientBuilder::create($options) ->setTransportFactory($transportFactory) ->getClient(); diff --git a/tests/phpt/error_handler_captures_fatal_error.phpt b/tests/phpt/error_handler_captures_fatal_error.phpt index 1e970c329..2f684a12a 100644 --- a/tests/phpt/error_handler_captures_fatal_error.phpt +++ b/tests/phpt/error_handler_captures_fatal_error.phpt @@ -46,7 +46,11 @@ $transportFactory = new class implements TransportFactoryInterface { } }; -$client = ClientBuilder::create([]) +$options = [ + 'dsn' => 'http://public@example.com/sentry/1', +]; + +$client = ClientBuilder::create($options) ->setTransportFactory($transportFactory) ->getClient(); diff --git a/tests/phpt/error_handler_respects_capture_silenced_errors_option.phpt b/tests/phpt/error_handler_respects_capture_silenced_errors_option.phpt index b03612bf7..ac2c4e223 100644 --- a/tests/phpt/error_handler_respects_capture_silenced_errors_option.phpt +++ b/tests/phpt/error_handler_respects_capture_silenced_errors_option.phpt @@ -47,7 +47,12 @@ $transportFactory = new class implements TransportFactoryInterface { } }; -$client = ClientBuilder::create(['capture_silenced_errors' => true]) +$options = [ + 'dsn' => 'http://public@example.com/sentry/1', + 'capture_silenced_errors' => true +]; + +$client = ClientBuilder::create($options) ->setTransportFactory($transportFactory) ->getClient(); diff --git a/tests/phpt/error_handler_respects_current_error_reporting_level.phpt b/tests/phpt/error_handler_respects_current_error_reporting_level.phpt index 44db31512..6b4d8e93c 100644 --- a/tests/phpt/error_handler_respects_current_error_reporting_level.phpt +++ b/tests/phpt/error_handler_respects_current_error_reporting_level.phpt @@ -10,8 +10,16 @@ declare(strict_types=1); namespace Sentry\Tests; +use GuzzleHttp\Promise\FulfilledPromise; +use GuzzleHttp\Promise\PromiseInterface; use Sentry\ClientBuilder; +use Sentry\Event; +use Sentry\Options; +use Sentry\Response; +use Sentry\ResponseStatus; use Sentry\SentrySdk; +use Sentry\Transport\TransportFactoryInterface; +use Sentry\Transport\TransportInterface; $vendor = __DIR__; @@ -21,14 +29,36 @@ while (!file_exists($vendor . '/vendor')) { require $vendor . '/vendor/autoload.php'; -$client = ClientBuilder::create([ +$transportFactory = new class implements TransportFactoryInterface { + public function create(Options $options): TransportInterface + { + return new class implements TransportInterface { + public function send(Event $event): PromiseInterface + { + return new FulfilledPromise(new Response(ResponseStatus::success())); + } + + public function close(?int $timeout = null): PromiseInterface + { + return new FulfilledPromise(true); + } + }; + } +}; + +$options = [ + 'dsn' => 'http://public@example.com/sentry/1', 'error_types' => null, 'before_send' => static function () { echo 'Before send callback called' . PHP_EOL; return null; }, -])->getClient(); +]; + +$client = ClientBuilder::create($options) + ->setTransportFactory($transportFactory) + ->getClient(); SentrySdk::getCurrentHub()->bindClient($client); diff --git a/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt b/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt index bd73e1208..e47750b5c 100644 --- a/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt +++ b/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt @@ -47,7 +47,12 @@ $transportFactory = new class implements TransportFactoryInterface { error_reporting(E_ALL & ~E_USER_NOTICE & ~E_USER_WARNING & ~E_USER_ERROR); -$client = ClientBuilder::create(['error_types' => E_ALL & ~E_USER_WARNING]) +$options = [ + 'dsn' => 'http://public@example.com/sentry/1', + 'error_types' => E_ALL & ~E_USER_WARNING, +]; + +$client = ClientBuilder::create($options) ->setTransportFactory($transportFactory) ->getClient();