From 2c4c15823bd1ee835237028cda624e111a8010fa Mon Sep 17 00:00:00 2001 From: o0h Date: Tue, 30 Mar 2021 21:43:24 +0900 Subject: [PATCH 01/46] Require entry/sentry:^3.0 --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 496d2b7..65b8c91 100644 --- a/composer.json +++ b/composer.json @@ -5,14 +5,14 @@ "require": { "php": "^7.2", "cakephp/cakephp": "^4.0", - "php-http/guzzle6-adapter": "^v1.1.1|^v2.0", - "sentry/sentry": "^2.2" + "sentry/sentry": "^3.0" }, "require-dev": { "cakephp/cakephp-codesniffer": "^3.0", "jangregor/phpstan-prophecy": "^0.4.2", "phpstan/phpstan": "@stable", - "phpunit/phpunit": "^8.5.0" + "phpunit/phpunit": "^8.5.0", + "symfony/http-client": "^5.2" }, "license": "MIT", "autoload": { From a00e99b7f2ddf5170bfb565f0f6e25ade4f3ea25 Mon Sep 17 00:00:00 2001 From: o0h Date: Tue, 30 Mar 2021 21:43:57 +0900 Subject: [PATCH 02/46] Require cakephp/cakephp-codesniffer 3.0 to @stable --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 65b8c91..57c38c5 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "sentry/sentry": "^3.0" }, "require-dev": { - "cakephp/cakephp-codesniffer": "^3.0", + "cakephp/cakephp-codesniffer": "@stable", "jangregor/phpstan-prophecy": "^0.4.2", "phpstan/phpstan": "@stable", "phpunit/phpunit": "^8.5.0", From 24e5f648f76b6f166133ee03de1fc97591d25e0c Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 13:43:53 +0900 Subject: [PATCH 03/46] Make it possible to handle excluded_exceptions by following SDK changes. --- src/Http/Client.php | 25 +++++++++++++++++ tests/TestCase/Http/ClientTest.php | 43 ++++++++++++++++++------------ 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index 80c8759..0bdb658 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -10,6 +10,7 @@ use Psr\Http\Message\ServerRequestInterface; use RuntimeException; use Sentry\Breadcrumb; +use Sentry\Integration\IntegrationInterface; use Sentry\SentrySdk; use Sentry\Severity; use Sentry\State\Hub; @@ -101,15 +102,39 @@ public function capture($level, string $message, array $context): void */ protected function setupClient(): void { + $integrationConfig = (array)Configure::consume('Sentry.integrations'); $config = (array)Configure::read('Sentry'); if (!Hash::check($config, 'dsn')) { throw new RuntimeException('Sentry DSN not provided.'); } + $config += ['integrations' => $this->buildIntegrations($integrationConfig)]; + init($config); $this->hub = SentrySdk::getCurrentHub(); $event = new Event('CakeSentry.Client.afterSetup', $this); $this->getEventManager()->dispatch($event); } + + /** + * Build configured integrations + * + * Config should be written as `Sentry.integrations`. + * The content is in the following form + * key: IntegrationClassName, value: Options + * + * @example $integrationConfig = [IgnoreErrorsIntegration => ['ignore_exceptions' => \RuntimeException::class]] + * @param array $integrationConfig + * @return array + */ + protected function buildIntegrations(array $integrationConfig): array + { + $integrations = []; + foreach ($integrationConfig as $integration => $options) { + $integrations[] = new $integration($options); + } + + return $integrations; + } } diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 3c1504b..7b7ad8a 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -16,6 +16,7 @@ use ReflectionProperty; use RuntimeException; use Sentry\ClientInterface; +use Sentry\Integration\IgnoreErrorsIntegration; use Sentry\Options; use Sentry\Severity; use Sentry\State\Hub; @@ -59,27 +60,35 @@ public function testSetupClientNotHasDsn(): void */ public function testSetupClientSetOptions(): void { - Configure::write('Sentry.excluded_exceptions', [NotFoundException::class]); - $beforeSend = (new class - { - public function __invoke() - { - return true; - } - }); - Configure::write('Sentry.before_send', $beforeSend); + Configure::write('Sentry.server_name', 'test-server'); $subject = new Client([]); $options = $subject->getHub()->getClient()->getOptions(); - $this->assertSame( - [NotFoundException::class], - $options->getExcludedExceptions() - ); - $this->assertSame( - get_class($beforeSend), - get_class($options->getBeforeSendCallback()) - ); + $this->assertSame('test-server', $options->getServerName()); + } + + /** + * Check constructor set up integrations + */ + public function testSetupClientSetIntegrations(): void + { + $ignoreErrors = [NotFoundException::class]; + Configure::write('Sentry.integrations', [ + IgnoreErrorsIntegration::class => [ + 'ignore_exceptions' => $ignoreErrors, + ] + ]); + + $subject = new Client([]); + + $actualIntegration = $subject->getHub()->getIntegration(IgnoreErrorsIntegration::class); + $actualIntegrationProperty = new ReflectionProperty($actualIntegration, 'options'); + $actualIntegrationProperty->setAccessible(true); + $actualIntegrationOption = $actualIntegrationProperty->getValue($actualIntegration); + + $this->assertSame($ignoreErrors, $actualIntegrationOption['ignore_exceptions']); + } /** From 86719d529930d397f731f3829bf420d4d435417b Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 13:49:56 +0900 Subject: [PATCH 04/46] Make the captureMessage() call test pass to follow SDK changes. --- tests/TestCase/Http/ClientTest.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 7b7ad8a..d0a63e2 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -16,6 +16,7 @@ use ReflectionProperty; use RuntimeException; use Sentry\ClientInterface; +use Sentry\EventId; use Sentry\Integration\IgnoreErrorsIntegration; use Sentry\Options; use Sentry\Severity; @@ -141,7 +142,7 @@ public function testCaptureException(): void ); $sentryClientP - ->captureException($exception, Argument::type(Scope::class)) + ->captureException($exception, Argument::type(Scope::class), null) ->shouldHaveBeenCalled(); } @@ -159,9 +160,15 @@ public function testCaptureError(): array ->captureMessage( 'some error', Severity::fromError(E_WARNING), - Argument::type(Scope::class) + Argument::type(Scope::class), + null ) - ->shouldBeCalled(); + ->shouldBeCalled() + ->willReturn(EventId::generate()); + // NOTE: + // This itself is not of interest for the test case, + // but for ProphecyMock's technical reasons, the return-value needs to be a real `EvnetId` + $subject->getHub()->bindClient($sentryClientP->reveal()); $subject->capture( @@ -224,9 +231,15 @@ public function testCaptureErrorBuildBreadcrumbs(): void } return true; - }) + }), + null ) - ->shouldBeCalled(); + ->shouldBeCalled() + ->willReturn(EventId::generate()); + // NOTE: + // This itself is not of interest for the test case, + // but for ProphecyMock's technical reasons, the return-value needs to be a real `EvnetId` + $subject->getHub()->bindClient($sentryClientP->reveal()); $subject->capture('warning', 'some error', []); @@ -259,7 +272,7 @@ function () use (&$called) { */ public function testCaptureDispatchAfterCapture(): void { - $lastEventId = 'aaa'; + $lastEventId = EventId::generate(); $subject = new Client([]); $sentryClientP = $this->prophesize(ClientInterface::class); From 0416b7b9db0b09825219789c8ba68aae1fd207bc Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 14:02:51 +0900 Subject: [PATCH 05/46] Ensure that the test more clearly indicates the content of the test --- tests/TestCase/Http/ClientTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index d0a63e2..afba717 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -143,7 +143,7 @@ public function testCaptureException(): void $sentryClientP ->captureException($exception, Argument::type(Scope::class), null) - ->shouldHaveBeenCalled(); + ->shouldHaveBeenCalledOnce(); } /** @@ -155,7 +155,7 @@ public function testCaptureError(): array { $subject = new Client([]); $sentryClientP = $this->prophesize(ClientInterface::class); - $sentryClientP->getOptions()->shouldBeCalled()->willReturn(new Options()); + $sentryClientP->getOptions()->willReturn(new Options()); $sentryClientP ->captureMessage( 'some error', @@ -163,7 +163,7 @@ public function testCaptureError(): array Argument::type(Scope::class), null ) - ->shouldBeCalled() + ->shouldBeCalledOnce() ->willReturn(EventId::generate()); // NOTE: // This itself is not of interest for the test case, @@ -214,7 +214,7 @@ public function testCaptureErrorBuildBreadcrumbs(): void $subject = new Client([]); $sentryClientP = $this->prophesize(ClientInterface::class); - $sentryClientP->getOptions()->shouldBeCalled()->willReturn(new Options()); + $sentryClientP->getOptions()->willReturn(new Options()); $sentryClientP ->captureMessage( Argument::any(), @@ -234,7 +234,7 @@ public function testCaptureErrorBuildBreadcrumbs(): void }), null ) - ->shouldBeCalled() + ->shouldBeCalledOnce() ->willReturn(EventId::generate()); // NOTE: // This itself is not of interest for the test case, @@ -277,7 +277,7 @@ public function testCaptureDispatchAfterCapture(): void $subject = new Client([]); $sentryClientP = $this->prophesize(ClientInterface::class); $sentryClientP->captureException(Argument::cetera()) - ->shouldBeCalled() + ->shouldBeCalledOnce() ->willReturn($lastEventId); $subject->getHub()->bindClient($sentryClientP->reveal()); From 855573745d41fbf1b263f3dd603e9bad35746915 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 14:04:57 +0900 Subject: [PATCH 06/46] Add a dependency for test_app to work with the new plugin. --- tests/test_app/app/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_app/app/composer.json b/tests/test_app/app/composer.json index c76eaa6..d278e12 100644 --- a/tests/test_app/app/composer.json +++ b/tests/test_app/app/composer.json @@ -24,7 +24,8 @@ "cakephp/debug_kit": "^4.0", "josegonzalez/dotenv": "^3.2", "phpunit/phpunit": "^8.5", - "psy/psysh": "@stable" + "psy/psysh": "@stable", + "symfony/http-client": "^5.2" }, "suggest": { "markstory/asset_compress": "An asset compression plugin which provides file concatenation and a flexible filter system for preprocessing and minification.", From c06e6137f5cbdf92b21e91892079de1b8bef3bae Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 14:05:20 +0900 Subject: [PATCH 07/46] Add a new form of configuration to test_app --- tests/test_app/app/config/bootstrap.php | 1 + tests/test_app/app/config/sentry.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/test_app/app/config/sentry.php diff --git a/tests/test_app/app/config/bootstrap.php b/tests/test_app/app/config/bootstrap.php index 9f417a0..c74878c 100644 --- a/tests/test_app/app/config/bootstrap.php +++ b/tests/test_app/app/config/bootstrap.php @@ -79,6 +79,7 @@ try { Configure::config('default', new PhpConfig()); Configure::load('app', 'default', false); + Configure::load('sentry', 'default'); } catch (\Exception $e) { exit($e->getMessage() . "\n"); } diff --git a/tests/test_app/app/config/sentry.php b/tests/test_app/app/config/sentry.php new file mode 100644 index 0000000..3639980 --- /dev/null +++ b/tests/test_app/app/config/sentry.php @@ -0,0 +1,17 @@ + [ + 'dsn' => env('SENTRY_DSN'), + 'integrations' => [ + IgnoreErrorsIntegration::class => [ + 'ignore_exceptions' => [ + NotFoundException::class, + ], + ], + ], + ], +]; From 5ecaa9ffd34f9b1cb3c7e0798f9a403be96cb112 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 14:44:39 +0900 Subject: [PATCH 08/46] Fix phpcs --- src/Http/Client.php | 2 +- tests/TestCase/Http/ClientTest.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index 0bdb658..8a5cf47 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -125,7 +125,7 @@ protected function setupClient(): void * key: IntegrationClassName, value: Options * * @example $integrationConfig = [IgnoreErrorsIntegration => ['ignore_exceptions' => \RuntimeException::class]] - * @param array $integrationConfig + * @param array $integrationConfig Integration with options map * @return array */ protected function buildIntegrations(array $integrationConfig): array diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index afba717..7ba8adc 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -78,7 +78,7 @@ public function testSetupClientSetIntegrations(): void Configure::write('Sentry.integrations', [ IgnoreErrorsIntegration::class => [ 'ignore_exceptions' => $ignoreErrors, - ] + ], ]); $subject = new Client([]); @@ -89,7 +89,6 @@ public function testSetupClientSetIntegrations(): void $actualIntegrationOption = $actualIntegrationProperty->getValue($actualIntegration); $this->assertSame($ignoreErrors, $actualIntegrationOption['ignore_exceptions']); - } /** @@ -184,7 +183,6 @@ public function testCaptureError(): array * Test capture error compatible with the error-level is specified by int or string * * @depends testCaptureError - * * @param array&array $mockMethodList */ public function testCaptureErrorWithErrorLevelInteger(array $mockMethodList): void From 45fc82fa403f029fb20470449bc53a8522169688 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 15:47:56 +0900 Subject: [PATCH 09/46] Fix phpcs --- src/Error/ConsoleErrorHandler.php | 1 + src/Error/ErrorHandler.php | 2 ++ src/Error/ErrorHandlerTrait.php | 3 +-- src/Error/ErrorLogger.php | 1 - src/Http/Client.php | 9 ++++----- src/Log/Engine/SentryLog.php | 5 +++-- src/Plugin.php | 1 + tests/TestCase/Error/ErrorHandlerTraitTest.php | 2 +- tests/TestCase/Error/ErrorLoggerTest.php | 4 +++- tests/TestCase/Log/Engine/SentryLogTest.php | 6 ++++-- 10 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Error/ConsoleErrorHandler.php b/src/Error/ConsoleErrorHandler.php index d523a07..155a734 100644 --- a/src/Error/ConsoleErrorHandler.php +++ b/src/Error/ConsoleErrorHandler.php @@ -1,4 +1,5 @@ hub->addBreadcrumb(new Breadcrumb( - $severity, + (string)$severity, Breadcrumb::TYPE_ERROR, 'method', $method, @@ -126,7 +125,7 @@ protected function setupClient(): void * * @example $integrationConfig = [IgnoreErrorsIntegration => ['ignore_exceptions' => \RuntimeException::class]] * @param array $integrationConfig Integration with options map - * @return array + * @return array<\Sentry\Integration\IntegrationInterface> */ protected function buildIntegrations(array $integrationConfig): array { diff --git a/src/Log/Engine/SentryLog.php b/src/Log/Engine/SentryLog.php index 5403451..57e0efa 100644 --- a/src/Log/Engine/SentryLog.php +++ b/src/Log/Engine/SentryLog.php @@ -1,4 +1,5 @@ Date: Sat, 10 Apr 2021 15:57:27 +0900 Subject: [PATCH 10/46] Fix type error --- src/Http/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index 7c762bc..c829a98 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -69,7 +69,7 @@ public function capture($level, string $message, array $context): void $lastEventId = $this->hub->captureException($exception); } else { $stacks = array_slice(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT), 3); - if (method_exists(Severity::class, $level)) { + if (is_string($level) && method_exists(Severity::class, $level)) { $severity = (Severity::class . '::' . $level)(); } else { $severity = Severity::fromError($level); From 4f35742cb3a05117707a11762caadc5d78baa691 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 14:05:55 +0900 Subject: [PATCH 11/46] Dealing with deprecated CakePHP --- tests/test_app/app/composer.json | 1 - tests/test_app/app/config/routes.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_app/app/composer.json b/tests/test_app/app/composer.json index d278e12..ddfd772 100644 --- a/tests/test_app/app/composer.json +++ b/tests/test_app/app/composer.json @@ -46,7 +46,6 @@ "scripts": { "post-install-cmd": "TestApp\\Console\\Installer::postInstall", "post-create-project-cmd": "TestApp\\Console\\Installer::postInstall", - "post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump", "check": [ "@test", "@cs-check" diff --git a/tests/test_app/app/config/routes.php b/tests/test_app/app/config/routes.php index 948661b..a6bfef3 100644 --- a/tests/test_app/app/config/routes.php +++ b/tests/test_app/app/config/routes.php @@ -48,7 +48,7 @@ $routes->scope('/', function (RouteBuilder $builder) { // Register scoped middleware for in scopes. $builder->registerMiddleware('csrf', new CsrfProtectionMiddleware([ - 'httpOnly' => true, + 'httponly' => true, ])); /* From 8698ed5aaa060c65713c90d5dcd61208da9a69c0 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 21:15:41 +0900 Subject: [PATCH 12/46] Install Composer programmatically --- tests/test_app/Dockerfile | 5 ++--- tests/test_app/composer-install.sh | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100755 tests/test_app/composer-install.sh diff --git a/tests/test_app/Dockerfile b/tests/test_app/Dockerfile index 22b8562..5c6d94e 100644 --- a/tests/test_app/Dockerfile +++ b/tests/test_app/Dockerfile @@ -12,8 +12,7 @@ RUN echo -e "zend_extension = xdebug.so\n" \ "xdebug.idekey = CAKE_SENTRY_TEST_APP\n" \ > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini -RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ - && php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \ - && php composer-setup.php \ +COPY tests/test_app/composer-install.sh /usr/bin/composer-install +RUN composer-install \ && mv composer.phar /usr/bin/composer WORKDIR /app diff --git a/tests/test_app/composer-install.sh b/tests/test_app/composer-install.sh new file mode 100755 index 0000000..a61aff8 --- /dev/null +++ b/tests/test_app/composer-install.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')" +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" + +if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ] +then + >&2 echo 'ERROR: Invalid installer checksum' + rm composer-setup.php + exit 1 +fi + +php composer-setup.php --quiet +RESULT=$? +rm composer-setup.php +exit $RESULT From b9153e4b952f04b7f2d5e0f9ee3fe8decc406a0a Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 21:15:54 +0900 Subject: [PATCH 13/46] Use docker-compose envfile --- tests/test_app/app.env.example | 5 +++++ tests/test_app/docker-compose.yml | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 tests/test_app/app.env.example diff --git a/tests/test_app/app.env.example b/tests/test_app/app.env.example new file mode 100644 index 0000000..36c2830 --- /dev/null +++ b/tests/test_app/app.env.example @@ -0,0 +1,5 @@ +# Please set your Sentry project's DSN +# @see https://sentry.io/settings/$your-sentry-account/projects/$your-sentry-pj/keys/ +SENTRY_DSN="https://xxx@xxxx.sentry.io/xxxxxxx" +XDEBUG_SESSION="CAKE_SENTRY_TEST_APP" +PHP_IDE_CONFIG="serverName=CAKE_SENTRY_TEST_APP" \ No newline at end of file diff --git a/tests/test_app/docker-compose.yml b/tests/test_app/docker-compose.yml index 8d3c28f..7720ed3 100644 --- a/tests/test_app/docker-compose.yml +++ b/tests/test_app/docker-compose.yml @@ -8,6 +8,8 @@ services: - ../..:/app ports: - "8080:80" + env_file: + - app.env container_name: cake-sentry-test-app build: context: ../.. From 1f6d7ad73b778ab331b2c61d30b5ec51a54f7b76 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 21:16:10 +0900 Subject: [PATCH 14/46] Add Sentry context cakephp-ver. --- tests/test_app/app/src/Error/Event/SentryErrorContext.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_app/app/src/Error/Event/SentryErrorContext.php b/tests/test_app/app/src/Error/Event/SentryErrorContext.php index ffc184b..4be97ed 100644 --- a/tests/test_app/app/src/Error/Event/SentryErrorContext.php +++ b/tests/test_app/app/src/Error/Event/SentryErrorContext.php @@ -3,6 +3,7 @@ namespace TestApp\Error\Event; +use Cake\Core\Configure; use Cake\Event\Event; use Cake\Event\EventListenerInterface; use Cake\Http\ServerRequest; @@ -41,6 +42,7 @@ public function setContext(Event $event): void sentryConfigureScope(function (Scope $scope) use ($request, $event) { $scope->setTag('app_version', $request->getHeaderLine('App-Version') ?: '1.0'); + $scope->setTag('cakephp_version', Configure::version()); $exception = $event->getData('exception'); if ($exception) { assert($exception instanceof \Throwable); From 3d0888b088c1c5e1b4a05e0eb6fa6d24e24f64fc Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 21:55:44 +0900 Subject: [PATCH 15/46] Adapt to Xdebug3 --- tests/test_app/Dockerfile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/test_app/Dockerfile b/tests/test_app/Dockerfile index 5c6d94e..04ebc45 100644 --- a/tests/test_app/Dockerfile +++ b/tests/test_app/Dockerfile @@ -5,11 +5,10 @@ WORKDIR /usr/src/php/ext RUN git clone https://github.com/xdebug/xdebug RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ docker-php-ext-install -j${NPROC} intl xdebug pdo_mysql -RUN echo -e "zend_extension = xdebug.so\n" \ - "xdebug.remote_enable = On\n" \ - "xdebug.remote_autostart = On\n" \ - "xdebug.remote_host = host.docker.internal\n" \ - "xdebug.idekey = CAKE_SENTRY_TEST_APP\n" \ +RUN echo -e "zend_extension=xdebug.so\n" \ + "xdebug.client_host=host.docker.internal\n" \ + "xdebug.start_with_request=yes\n" \ + "xdebug.mode=debug" \ > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini COPY tests/test_app/composer-install.sh /usr/bin/composer-install From f054f65514601c35790994b8e2e57b0d02a86a7e Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 21:56:58 +0900 Subject: [PATCH 16/46] Make the container's working directory the application directory of test_app --- tests/test_app/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_app/docker-compose.yml b/tests/test_app/docker-compose.yml index 7720ed3..e48cc0d 100644 --- a/tests/test_app/docker-compose.yml +++ b/tests/test_app/docker-compose.yml @@ -15,3 +15,4 @@ services: context: ../.. dockerfile: ./tests/test_app/Dockerfile command: bash -c "/app/tests/test_app/app/bin/cake server -H 0.0.0.0 -p 80" + working_dir: /app/tests/test_app/app From 0d267318e817685b9e57fa35d9423f6cd40571fe Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 22:23:29 +0900 Subject: [PATCH 17/46] Create commands to check the behavior in the CLI --- .../test_app/app/src/Command/ErrorCommand.php | 46 +++++++++++++++++++ .../app/src/Command/ExceptionCommand.php | 33 +++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/test_app/app/src/Command/ErrorCommand.php create mode 100644 tests/test_app/app/src/Command/ExceptionCommand.php diff --git a/tests/test_app/app/src/Command/ErrorCommand.php b/tests/test_app/app/src/Command/ErrorCommand.php new file mode 100644 index 0000000..96e3b3f --- /dev/null +++ b/tests/test_app/app/src/Command/ErrorCommand.php @@ -0,0 +1,46 @@ + 'notice!!', + E_USER_DEPRECATED => 'deprecated!!', + E_USER_WARNING => 'warning!!', + E_USER_ERROR => 'error!!', + ]; + + foreach ($errorLevels as $errorLevel => $errorMessage) { + $this->triggerError($errorLevel, $errorMessage); + + } + } + + /** + * @param int $level user error level + * @param string $message error message + * @return void + */ + private function triggerError(int $level, string $message) + { + trigger_error($message, $level); + } +} diff --git a/tests/test_app/app/src/Command/ExceptionCommand.php b/tests/test_app/app/src/Command/ExceptionCommand.php new file mode 100644 index 0000000..6c814bc --- /dev/null +++ b/tests/test_app/app/src/Command/ExceptionCommand.php @@ -0,0 +1,33 @@ +throwBadMethodCallException('some exception'); + } + + /** + * @param string $message exception message + * @return never-return + */ + private function throwBadMethodCallException(string $message) + { + throw new \BadMethodCallException($message); + } +} From d326aab9f3f81fa15f7bae86c11111af3818cd6b Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 10 Apr 2021 22:45:02 +0900 Subject: [PATCH 18/46] Add information to be sent when running on the CLI --- .../app/src/Command/ExceptionCommand.php | 17 +++++++++++++++++ .../app/src/Error/Event/SentryErrorContext.php | 11 +++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/test_app/app/src/Command/ExceptionCommand.php b/tests/test_app/app/src/Command/ExceptionCommand.php index 6c814bc..9d994ab 100644 --- a/tests/test_app/app/src/Command/ExceptionCommand.php +++ b/tests/test_app/app/src/Command/ExceptionCommand.php @@ -6,12 +6,29 @@ use Cake\Command\Command; use Cake\Console\Arguments; use Cake\Console\ConsoleIo; +use Cake\Console\ConsoleOptionParser; /** * A Command for checking the behavior of the CLI when an exception occurs */ class ExceptionCommand extends Command { + /** + * @inheritDoc + */ + protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser + { + $parser->addOption('placebo', [ + 'short' => 'p', + 'default' => true + ]); + $parser->addArgument('placebo-arg', [ + 'help' => 'A meaningless argument', + ]); + + return parent::buildOptionParser($parser); + } + /** * {@inheritDoc} * diff --git a/tests/test_app/app/src/Error/Event/SentryErrorContext.php b/tests/test_app/app/src/Error/Event/SentryErrorContext.php index 4be97ed..afa1027 100644 --- a/tests/test_app/app/src/Error/Event/SentryErrorContext.php +++ b/tests/test_app/app/src/Error/Event/SentryErrorContext.php @@ -30,7 +30,7 @@ public function setServerContext(Event $event): void $options = $subject->getHub()->getClient()->getOptions(); $options->setEnvironment('test_app'); - $options->setRelease('2.0.0@dev'); + $options->setRelease('4.0.0@dev'); } public function setContext(Event $event): void @@ -42,7 +42,6 @@ public function setContext(Event $event): void sentryConfigureScope(function (Scope $scope) use ($request, $event) { $scope->setTag('app_version', $request->getHeaderLine('App-Version') ?: '1.0'); - $scope->setTag('cakephp_version', Configure::version()); $exception = $event->getData('exception'); if ($exception) { assert($exception instanceof \Throwable); @@ -54,6 +53,14 @@ public function setContext(Event $event): void 'request attributes' => $request->getAttributes(), ]); }); + } else { + sentryConfigureScope(function (Scope $scope) use ($event) { + $argv = env('argv'); + array_shift($argv); + array_unshift($argv, env('_')); + $scope->setExtra('command', implode(' ', $argv)); + $scope->setTag('cakephp_version', Configure::version()); + }); } } From 2b988c493aa76d6f80b27e1d50a9fc1698373059 Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 00:30:56 +0900 Subject: [PATCH 19/46] Update dependencies and platform-reqs for php8 --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 57c38c5..cc0517f 100644 --- a/composer.json +++ b/composer.json @@ -3,15 +3,15 @@ "description": "Sentry plugin for CakePHP", "type": "cakephp-plugin", "require": { - "php": "^7.2", + "php": "^7.2 || ^8.0", "cakephp/cakephp": "^4.0", "sentry/sentry": "^3.0" }, "require-dev": { "cakephp/cakephp-codesniffer": "@stable", - "jangregor/phpstan-prophecy": "^0.4.2", + "jangregor/phpstan-prophecy": "^0.8", "phpstan/phpstan": "@stable", - "phpunit/phpunit": "^8.5.0", + "phpunit/phpunit": "^8.5 || ^9.3", "symfony/http-client": "^5.2" }, "license": "MIT", From 25bc4554599b61de9c2a14b23900b7f0c80b53bd Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 00:33:19 +0900 Subject: [PATCH 20/46] Update test_app dependencies --- tests/test_app/app/composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_app/app/composer.json b/tests/test_app/app/composer.json index ddfd772..458e477 100644 --- a/tests/test_app/app/composer.json +++ b/tests/test_app/app/composer.json @@ -19,11 +19,11 @@ "mobiledetect/mobiledetectlib": "^2.8" }, "require-dev": { - "cakephp/bake": "^2.0.3", - "cakephp/cakephp-codesniffer": "~4.0.0", - "cakephp/debug_kit": "^4.0", - "josegonzalez/dotenv": "^3.2", - "phpunit/phpunit": "^8.5", + "cakephp/bake": "@stable", + "cakephp/cakephp-codesniffer": "@stable", + "cakephp/debug_kit": "@stable", + "josegonzalez/dotenv": "@stable", + "phpunit/phpunit": "^8.5 || ^9.3", "psy/psysh": "@stable", "symfony/http-client": "^5.2" }, From 7c2dcb0e2e1c19dce40ab5e3a8c45ea11bf05714 Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 00:38:51 +0900 Subject: [PATCH 21/46] Fix deprecated --- composer.json | 1 + tests/TestCase/Http/ClientTest.php | 3 +++ 2 files changed, 4 insertions(+) diff --git a/composer.json b/composer.json index cc0517f..f2a1b4c 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ "require-dev": { "cakephp/cakephp-codesniffer": "@stable", "jangregor/phpstan-prophecy": "^0.8", + "phpspec/prophecy-phpunit": "@stable", "phpstan/phpstan": "@stable", "phpunit/phpunit": "^8.5 || ^9.3", "symfony/http-client": "^5.2" diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 7ba8adc..b6ad07f 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -12,6 +12,7 @@ use Connehito\CakeSentry\Http\Client; use Exception; use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\MethodProphecy; use ReflectionProperty; use RuntimeException; @@ -25,6 +26,8 @@ final class ClientTest extends TestCase { + use ProphecyTrait; + /** * @inheritDoc */ From 35b5d2b25b81a495b1af85289399d8f9c2fafbec Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 00:39:03 +0900 Subject: [PATCH 22/46] Add test_app service for php7 --- tests/test_app/Dockerfile.php7 | 17 +++++++++++++++++ tests/test_app/docker-compose.yml | 10 +++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/test_app/Dockerfile.php7 diff --git a/tests/test_app/Dockerfile.php7 b/tests/test_app/Dockerfile.php7 new file mode 100644 index 0000000..d645b89 --- /dev/null +++ b/tests/test_app/Dockerfile.php7 @@ -0,0 +1,17 @@ +FROM php:7-alpine +RUN apk add bash icu-dev git + +WORKDIR /usr/src/php/ext +RUN git clone https://github.com/xdebug/xdebug +RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ + docker-php-ext-install -j${NPROC} intl xdebug pdo_mysql +RUN echo -e "zend_extension=xdebug.so\n" \ + "xdebug.client_host=host.docker.internal\n" \ + "xdebug.start_with_request=trigger\n" \ + "xdebug.mode=debug" \ + > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini + +COPY tests/test_app/composer-install.sh /usr/bin/composer-install +RUN composer-install \ + && mv composer.phar /usr/bin/composer +WORKDIR /app diff --git a/tests/test_app/docker-compose.yml b/tests/test_app/docker-compose.yml index e48cc0d..b89650b 100644 --- a/tests/test_app/docker-compose.yml +++ b/tests/test_app/docker-compose.yml @@ -1,6 +1,6 @@ version: "3.7" services: - test-app: + test-app: &test-app volumes: - ../../src:/dist/src - ../../config:/dist/config @@ -16,3 +16,11 @@ services: dockerfile: ./tests/test_app/Dockerfile command: bash -c "/app/tests/test_app/app/bin/cake server -H 0.0.0.0 -p 80" working_dir: /app/tests/test_app/app + test-app-php7: + <<: *test-app + ports: + - "8081:80" + container_name: cake-sentry-test-app-php7 + build: + context: ../.. + dockerfile: ./tests/test_app/Dockerfile.php7 From dfcb9ef23fce8e363c01ce0d0c4072cd84b024b3 Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 00:42:43 +0900 Subject: [PATCH 23/46] Run CI on PHP8 --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a0b331a..3d91df5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ php: - 7.2 - 7.3 - 7.4 + - 8.0 cache: directories: @@ -15,9 +16,9 @@ env: matrix: include: - - php: 7.4 + - php: 8.0 env: PREFER_LOWEST="" TEST=1 CODECOV=1 STAN=0 - - php: 7.4 + - php: 8.0 env: PREFER_LOWEST="" TEST=0 CODECOV=0 STAN=1 before_script: From 1954eb378a732307150229988276442f47dcdbdc Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 01:16:20 +0900 Subject: [PATCH 24/46] Can't use phpspec/prophecy-phpunit under php7.2 --- .travis.yml | 1 + composer.json | 2 +- tests/bootstrap.php | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3d91df5..00b1474 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ matrix: before_script: - phpenv config-rm xdebug.ini + - if [[ $TRAVIS_PHP_VERSION = 7.2 ]]; then composer remove --dev phpspec/prophecy-phpunit; fi - composer update --prefer-dist --no-interaction $PREFER_LOWEST - composer show -i # @see https://github.com/cakephp/cakephp/pull/13567#issuecomment-525844184 diff --git a/composer.json b/composer.json index f2a1b4c..d6809b4 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "require-dev": { "cakephp/cakephp-codesniffer": "@stable", "jangregor/phpstan-prophecy": "^0.8", - "phpspec/prophecy-phpunit": "@stable", + "phpspec/prophecy-phpunit": "^2.0", "phpstan/phpstan": "@stable", "phpunit/phpunit": "^8.5 || ^9.3", "symfony/http-client": "^5.2" diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 061673b..2ae1f44 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -105,3 +105,19 @@ ini_set('session.gc_divisor', '1'); #loadPHPUnitAliases(); + +/** + * NOTE: + * Since PHPUnit 9.x, PHPUnit\Framework\TestCase::prophesize is marked as deprecated. + * To work around this issue, you need to use \Prophecy\PhpUnit\ProphecyTrait. + * However, this Trait is not supported under PHP 7.3. + * Declare a dummy Trait to avoid problems in PREFER_LOWEST mode. + */ +if (!trait_exists('\\Prophecy\\PhpUnit\\ProphecyTrait')) { + assert( + version_compare(phpversion(), '7.3.0') < 0, + 'If using PHP 7.3 or higher, should install phpspec/prophecy-phpunit' + ); + trait DoNothingTrait{} + class_alias(DoNothingTrait::class, '\\Prophecy\\PhpUnit\\ProphecyTrait'); +} From 38d45e8b7d48fa4fd759980daa59e8859fc7cbde Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 01:36:47 +0900 Subject: [PATCH 25/46] Enable assert.exception in TravisCI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 00b1474..02eaf37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ matrix: before_script: - phpenv config-rm xdebug.ini + - echo "assert.exception = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - if [[ $TRAVIS_PHP_VERSION = 7.2 ]]; then composer remove --dev phpspec/prophecy-phpunit; fi - composer update --prefer-dist --no-interaction $PREFER_LOWEST - composer show -i From 5abc67858f4cec94ac1ed1b7d58ce76a1bf875d7 Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 11 Apr 2021 01:39:36 +0900 Subject: [PATCH 26/46] Fix phpstan-prophecy problem --- composer.json | 2 +- phpstan.neon | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index d6809b4..1b09ede 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ }, "require-dev": { "cakephp/cakephp-codesniffer": "@stable", - "jangregor/phpstan-prophecy": "^0.8", + "jangregor/phpstan-prophecy": "@stable", "phpspec/prophecy-phpunit": "^2.0", "phpstan/phpstan": "@stable", "phpunit/phpunit": "^8.5 || ^9.3", diff --git a/phpstan.neon b/phpstan.neon index e0ae8f6..78c99ca 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ includes: -- vendor/jangregor/phpstan-prophecy/src/extension.neon +- vendor/jangregor/phpstan-prophecy/extension.neon parameters: paths: - src From c26f5df3117ed4f7cf74e5613f12b4a6a07cc00a Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 8 May 2021 14:23:53 +0900 Subject: [PATCH 27/46] xdebug.start_with_request=trigger(set default) --- tests/test_app/Dockerfile | 1 - tests/test_app/Dockerfile.php7 | 1 - tests/test_app/app.env.example | 6 ++++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_app/Dockerfile b/tests/test_app/Dockerfile index 04ebc45..52d9576 100644 --- a/tests/test_app/Dockerfile +++ b/tests/test_app/Dockerfile @@ -7,7 +7,6 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ docker-php-ext-install -j${NPROC} intl xdebug pdo_mysql RUN echo -e "zend_extension=xdebug.so\n" \ "xdebug.client_host=host.docker.internal\n" \ - "xdebug.start_with_request=yes\n" \ "xdebug.mode=debug" \ > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini diff --git a/tests/test_app/Dockerfile.php7 b/tests/test_app/Dockerfile.php7 index d645b89..a5b94a1 100644 --- a/tests/test_app/Dockerfile.php7 +++ b/tests/test_app/Dockerfile.php7 @@ -7,7 +7,6 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \ docker-php-ext-install -j${NPROC} intl xdebug pdo_mysql RUN echo -e "zend_extension=xdebug.so\n" \ "xdebug.client_host=host.docker.internal\n" \ - "xdebug.start_with_request=trigger\n" \ "xdebug.mode=debug" \ > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini diff --git a/tests/test_app/app.env.example b/tests/test_app/app.env.example index 36c2830..028c2a3 100644 --- a/tests/test_app/app.env.example +++ b/tests/test_app/app.env.example @@ -1,5 +1,7 @@ # Please set your Sentry project's DSN # @see https://sentry.io/settings/$your-sentry-account/projects/$your-sentry-pj/keys/ SENTRY_DSN="https://xxx@xxxx.sentry.io/xxxxxxx" -XDEBUG_SESSION="CAKE_SENTRY_TEST_APP" -PHP_IDE_CONFIG="serverName=CAKE_SENTRY_TEST_APP" \ No newline at end of file +PHP_IDE_CONFIG="serverName=CAKE_SENTRY_TEST_APP" +# If you want to enable Xdebug sessions, uncomment the following line +# see: https://xdebug.org/docs/step_debug#activate_debugger +# XDEBUG_SESSION=1 \ No newline at end of file From 1e364ec9bee78a2b721b73355985992150681aa9 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 8 May 2021 14:24:20 +0900 Subject: [PATCH 28/46] assert.exception=1 --- tests/test_app/Dockerfile | 2 ++ tests/test_app/Dockerfile.php7 | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/test_app/Dockerfile b/tests/test_app/Dockerfile index 52d9576..8b71f93 100644 --- a/tests/test_app/Dockerfile +++ b/tests/test_app/Dockerfile @@ -9,6 +9,8 @@ RUN echo -e "zend_extension=xdebug.so\n" \ "xdebug.client_host=host.docker.internal\n" \ "xdebug.mode=debug" \ > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo -e "assert.exception=1" \ + > /usr/local/etc/php/conf.d/assert.ini COPY tests/test_app/composer-install.sh /usr/bin/composer-install RUN composer-install \ diff --git a/tests/test_app/Dockerfile.php7 b/tests/test_app/Dockerfile.php7 index a5b94a1..0babe72 100644 --- a/tests/test_app/Dockerfile.php7 +++ b/tests/test_app/Dockerfile.php7 @@ -9,6 +9,8 @@ RUN echo -e "zend_extension=xdebug.so\n" \ "xdebug.client_host=host.docker.internal\n" \ "xdebug.mode=debug" \ > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo -e "assert.exception=1" \ + > /usr/local/etc/php/conf.d/assert.ini COPY tests/test_app/composer-install.sh /usr/bin/composer-install RUN composer-install \ From ddd3ecf2b777878f10a5fcd8c71bfc3e0734bcdd Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 8 May 2021 19:08:13 +0900 Subject: [PATCH 29/46] Docker image to php8 --- tests/test_app/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_app/Dockerfile b/tests/test_app/Dockerfile index 8b71f93..7052ed5 100644 --- a/tests/test_app/Dockerfile +++ b/tests/test_app/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7.4-alpine +FROM php:8-alpine RUN apk add bash icu-dev git WORKDIR /usr/src/php/ext From b01381538faf305fae68f040c5dd03d8b9698abf Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 9 May 2021 11:57:24 +0900 Subject: [PATCH 30/46] refactor: remove unused lines --- src/Http/Client.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index c829a98..d3578b7 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -8,7 +8,6 @@ use Cake\Event\Event; use Cake\Event\EventDispatcherTrait; use Cake\Utility\Hash; -use Psr\Http\Message\ServerRequestInterface; use RuntimeException; use Sentry\Breadcrumb; use Sentry\SentrySdk; @@ -27,9 +26,6 @@ class Client /* @var Hub */ protected $hub; - /* @var ServerRequestInterface */ - protected $request; - /** * Client constructor. * From 3bccf566b793e8b7a48b24f31cc30dab35d68c82 Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 9 May 2021 12:17:28 +0900 Subject: [PATCH 31/46] Fix phpcs --- tests/TestCase/Error/ErrorLoggerTest.php | 2 +- tests/TestCase/Http/ClientTest.php | 2 +- tests/test_app/app/src/Command/ErrorCommand.php | 1 - tests/test_app/app/src/Command/ExceptionCommand.php | 2 +- tests/test_app/app/src/Error/Event/SentryErrorContext.php | 2 -- 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Error/ErrorLoggerTest.php b/tests/TestCase/Error/ErrorLoggerTest.php index 8d1c26e..cddd5e1 100644 --- a/tests/TestCase/Error/ErrorLoggerTest.php +++ b/tests/TestCase/Error/ErrorLoggerTest.php @@ -9,7 +9,7 @@ use Cake\Log\Log; use Cake\TestSuite\TestCase; use Connehito\CakeSentry\Error\ErrorLogger; -use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\MockObject; // phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse use Psr\Log\LoggerInterface; use RuntimeException; diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index b6ad07f..8e3821c 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -13,7 +13,7 @@ use Exception; use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\MethodProphecy; +use Prophecy\Prophecy\MethodProphecy; // phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse use ReflectionProperty; use RuntimeException; use Sentry\ClientInterface; diff --git a/tests/test_app/app/src/Command/ErrorCommand.php b/tests/test_app/app/src/Command/ErrorCommand.php index 96e3b3f..ad3e37d 100644 --- a/tests/test_app/app/src/Command/ErrorCommand.php +++ b/tests/test_app/app/src/Command/ErrorCommand.php @@ -30,7 +30,6 @@ public function execute(Arguments $args, ConsoleIo $io) foreach ($errorLevels as $errorLevel => $errorMessage) { $this->triggerError($errorLevel, $errorMessage); - } } diff --git a/tests/test_app/app/src/Command/ExceptionCommand.php b/tests/test_app/app/src/Command/ExceptionCommand.php index 9d994ab..67a47b9 100644 --- a/tests/test_app/app/src/Command/ExceptionCommand.php +++ b/tests/test_app/app/src/Command/ExceptionCommand.php @@ -20,7 +20,7 @@ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOption { $parser->addOption('placebo', [ 'short' => 'p', - 'default' => true + 'default' => true, ]); $parser->addArgument('placebo-arg', [ 'help' => 'A meaningless argument', diff --git a/tests/test_app/app/src/Error/Event/SentryErrorContext.php b/tests/test_app/app/src/Error/Event/SentryErrorContext.php index afa1027..a58601b 100644 --- a/tests/test_app/app/src/Error/Event/SentryErrorContext.php +++ b/tests/test_app/app/src/Error/Event/SentryErrorContext.php @@ -6,9 +6,7 @@ use Cake\Core\Configure; use Cake\Event\Event; use Cake\Event\EventListenerInterface; -use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; -use Connehito\CakeSentry\Http\Client; use Sentry\State\Scope; use function Sentry\configureScope as sentryConfigureScope; From 91e0e451309d3b87a2078e9611cc069a0f239602 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 8 May 2021 19:50:13 +0900 Subject: [PATCH 32/46] Make integration permeable to injection --- src/Http/Client.php | 24 ------------------------ tests/TestCase/Http/ClientTest.php | 24 ------------------------ 2 files changed, 48 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index d3578b7..289d7d3 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -97,39 +97,15 @@ public function capture($level, string $message, array $context): void */ protected function setupClient(): void { - $integrationConfig = (array)Configure::consume('Sentry.integrations'); $config = (array)Configure::read('Sentry'); if (!Hash::check($config, 'dsn')) { throw new RuntimeException('Sentry DSN not provided.'); } - $config += ['integrations' => $this->buildIntegrations($integrationConfig)]; - init($config); $this->hub = SentrySdk::getCurrentHub(); $event = new Event('CakeSentry.Client.afterSetup', $this); $this->getEventManager()->dispatch($event); } - - /** - * Build configured integrations - * - * Config should be written as `Sentry.integrations`. - * The content is in the following form - * key: IntegrationClassName, value: Options - * - * @example $integrationConfig = [IgnoreErrorsIntegration => ['ignore_exceptions' => \RuntimeException::class]] - * @param array $integrationConfig Integration with options map - * @return array<\Sentry\Integration\IntegrationInterface> - */ - protected function buildIntegrations(array $integrationConfig): array - { - $integrations = []; - foreach ($integrationConfig as $integration => $options) { - $integrations[] = new $integration($options); - } - - return $integrations; - } } diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 8e3821c..1dfc83f 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -6,7 +6,6 @@ use Cake\Core\Configure; use Cake\Event\Event; use Cake\Event\EventManager; -use Cake\Http\Exception\NotFoundException; use Cake\TestSuite\TestCase; use Closure; use Connehito\CakeSentry\Http\Client; @@ -18,7 +17,6 @@ use RuntimeException; use Sentry\ClientInterface; use Sentry\EventId; -use Sentry\Integration\IgnoreErrorsIntegration; use Sentry\Options; use Sentry\Severity; use Sentry\State\Hub; @@ -72,28 +70,6 @@ public function testSetupClientSetOptions(): void $this->assertSame('test-server', $options->getServerName()); } - /** - * Check constructor set up integrations - */ - public function testSetupClientSetIntegrations(): void - { - $ignoreErrors = [NotFoundException::class]; - Configure::write('Sentry.integrations', [ - IgnoreErrorsIntegration::class => [ - 'ignore_exceptions' => $ignoreErrors, - ], - ]); - - $subject = new Client([]); - - $actualIntegration = $subject->getHub()->getIntegration(IgnoreErrorsIntegration::class); - $actualIntegrationProperty = new ReflectionProperty($actualIntegration, 'options'); - $actualIntegrationProperty->setAccessible(true); - $actualIntegrationOption = $actualIntegrationProperty->getValue($actualIntegration); - - $this->assertSame($ignoreErrors, $actualIntegrationOption['ignore_exceptions']); - } - /** * Check constructor fill before_send option */ From ee4481588b107897e441b80805ba935cfeddaeb1 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 8 May 2021 19:50:29 +0900 Subject: [PATCH 33/46] Update test-app config --- tests/test_app/app/config/sentry.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_app/app/config/sentry.php b/tests/test_app/app/config/sentry.php index 3639980..910b816 100644 --- a/tests/test_app/app/config/sentry.php +++ b/tests/test_app/app/config/sentry.php @@ -7,11 +7,11 @@ 'Sentry' => [ 'dsn' => env('SENTRY_DSN'), 'integrations' => [ - IgnoreErrorsIntegration::class => [ + new IgnoreErrorsIntegration([ 'ignore_exceptions' => [ NotFoundException::class, ], - ], + ]), ], ], ]; From b3cca8722390df3a76c2f3f5510ef1a1f6032806 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 8 May 2021 16:17:09 +0900 Subject: [PATCH 34/46] Add initial installation to handle more detailed context --- src/Http/Client.php | 17 +++++++++++++++-- tests/TestCase/Http/ClientTest.php | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index 289d7d3..d0a0ef4 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -21,7 +21,16 @@ class Client use InstanceConfigTrait; /* @var array default instance config */ - protected $_defaultConfig = []; + protected $_defaultConfig = [ + 'sentry' => [ + 'prefixes' => [ + APP, + ], + 'in_app_exclude' => [ + ROOT . DS . 'vendor' . DS, + ], + ], + ]; /* @var Hub */ protected $hub; @@ -33,6 +42,10 @@ class Client */ public function __construct(array $config) { + $userConfig = Configure::read('Sentry'); + if ($userConfig) { + $this->_defaultConfig['sentry'] = array_merge($this->_defaultConfig['sentry'], $userConfig); + } $this->setConfig($config); $this->setupClient(); } @@ -97,7 +110,7 @@ public function capture($level, string $message, array $context): void */ protected function setupClient(): void { - $config = (array)Configure::read('Sentry'); + $config = $this->getConfig('sentry'); if (!Hash::check($config, 'dsn')) { throw new RuntimeException('Sentry DSN not provided.'); } diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 1dfc83f..92ea876 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -46,6 +46,25 @@ public function testSetupClient(): void $this->assertInstanceOf(Hub::class, $subject->getHub()); } + /** + * Check the configuration values are merged into the default-config. + */ + public function testSetUpClientMergeConfig(): void + { + $userConfig = [ + 'dsn' => false, + 'in_app_exclude' => ['/app/vendor', '/app/tmp',], + 'server_name' => 'test-server', + ]; + + Configure::write('Sentry', $userConfig); + $subject = new Client([]); + + $this->assertSame([APP], $subject->getConfig('sentry.prefixes'), 'Default value not applied'); + $this->assertSame($userConfig['in_app_exclude'], $subject->getConfig('sentry.in_app_exclude'), 'Default value is not overwritten'); + $this->assertSame(false, $subject->getConfig('sentry.dsn'), 'Set value is not addes'); + } + /** * Check constructor throws exception unless dsn is given */ From e9fb0d0b05939e3f954677a6345d5df82f53db6c Mon Sep 17 00:00:00 2001 From: o0h Date: Sun, 9 May 2021 03:31:04 +0900 Subject: [PATCH 35/46] Use stacktrace instead of breadcrumbs in case of errors. --- src/Http/Client.php | 31 ++++++++++++++++-------------- tests/TestCase/Http/ClientTest.php | 25 ++++++++++++------------ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index d0a0ef4..045d8d7 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -9,9 +9,11 @@ use Cake\Event\EventDispatcherTrait; use Cake\Utility\Hash; use RuntimeException; -use Sentry\Breadcrumb; +use Sentry\EventHint; use Sentry\SentrySdk; +use Sentry\Serializer\RepresentationSerializer; use Sentry\Severity; +use Sentry\StacktraceBuilder; use Sentry\State\Hub; use function Sentry\init; @@ -35,6 +37,9 @@ class Client /* @var Hub */ protected $hub; + /* @var StacktraceBuilder */ + protected $stackTraceBuilder; + /** * Client constructor. * @@ -48,6 +53,10 @@ public function __construct(array $config) } $this->setConfig($config); $this->setupClient(); + $this->stackTraceBuilder = new StacktraceBuilder( + $this->getHub()->getClient()->getOptions(), + new RepresentationSerializer($this->getHub()->getClient()->getOptions()) + ); } /** @@ -83,19 +92,13 @@ public function capture($level, string $message, array $context): void } else { $severity = Severity::fromError($level); } - foreach ($stacks as $stack) { - $method = isset($stack['class']) ? "{$stack['class']}::{$stack['function']}" : $stack['function']; - unset($stack['class']); - unset($stack['function']); - $this->hub->addBreadcrumb(new Breadcrumb( - (string)$severity, - Breadcrumb::TYPE_ERROR, - 'method', - $method, - $stack - )); - } - $lastEventId = $this->hub->captureMessage($message, $severity); + $stackTrace = $this->stackTraceBuilder->buildFromBacktrace($stacks, $stacks[0]['file'], $stacks[0]['line']); + + $hint = new EventHint(); + $hint->extra = $context; + $hint->stacktrace = $stackTrace; + + $lastEventId = $this->hub->captureMessage($message, $severity, $hint); } $context['lastEventId'] = $lastEventId; diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 92ea876..5dc8bf9 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -13,9 +13,9 @@ use Prophecy\Argument; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\MethodProphecy; // phpcs:ignore SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse -use ReflectionProperty; use RuntimeException; use Sentry\ClientInterface; +use Sentry\EventHint; use Sentry\EventId; use Sentry\Options; use Sentry\Severity; @@ -158,7 +158,7 @@ public function testCaptureError(): array 'some error', Severity::fromError(E_WARNING), Argument::type(Scope::class), - null + Argument::type(EventHint::class) ) ->shouldBeCalledOnce() ->willReturn(EventId::generate()); @@ -215,20 +215,19 @@ public function testCaptureErrorBuildBreadcrumbs(): void ->captureMessage( Argument::any(), Argument::any(), - Argument::that(function ($a) use (&$expect) { - $breadcrumbsProp = new ReflectionProperty($a, 'breadcrumbs'); - $breadcrumbsProp->setAccessible(true); - $breadcrumbs = $breadcrumbsProp->getValue($a); - $metadata = $breadcrumbs[0]->getMetaData(); - foreach ($expect as $field => $val) { - if ($metadata[$field] !== $val) { - return false; - } + Argument::any(), + Argument::that(function (EventHint $a) use (&$expect) { + $frames = $a->stacktrace->getFrames(); + $actual = array_slice($frames, -2, 1)[0]; + if ($actual->getFile() !== $expect['file']) { + $this->fail('stacktrace "file" does not t match'); + } + if ($actual->getLine() !== $expect['line']) { + $this->fail('stacktrace "line" does not t match'); } return true; - }), - null + }) ) ->shouldBeCalledOnce() ->willReturn(EventId::generate()); From b3183519e982e9193414d81ab8e33c056fb77c59 Mon Sep 17 00:00:00 2001 From: o0h Date: Wed, 12 May 2021 01:10:02 +0900 Subject: [PATCH 36/46] Pass stackframe by LogEngine, not Client --- src/Http/Client.php | 14 ++++++++---- src/Log/Engine/SentryLog.php | 1 + tests/TestCase/Http/ClientTest.php | 24 +++++++++------------ tests/TestCase/Log/Engine/SentryLogTest.php | 6 +++++- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index 045d8d7..5d44431 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -86,18 +86,24 @@ public function capture($level, string $message, array $context): void if ($exception) { $lastEventId = $this->hub->captureException($exception); } else { - $stacks = array_slice(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT), 3); if (is_string($level) && method_exists(Severity::class, $level)) { $severity = (Severity::class . '::' . $level)(); } else { $severity = Severity::fromError($level); } - $stackTrace = $this->stackTraceBuilder->buildFromBacktrace($stacks, $stacks[0]['file'], $stacks[0]['line']); - $hint = new EventHint(); $hint->extra = $context; - $hint->stacktrace = $stackTrace; + $stackTrace = $context['stackTrace'] ?? false; + if ($stackTrace) { + $hint->stacktrace = $this->stackTraceBuilder->buildFromBacktrace( + $stackTrace, + $stackTrace[0]['file'], + $stackTrace[0]['line'] + ); + } + + $severity = $this->convertLevelToSeverity($level); $lastEventId = $this->hub->captureMessage($message, $severity, $hint); } diff --git a/src/Log/Engine/SentryLog.php b/src/Log/Engine/SentryLog.php index 57e0efa..87cfae2 100644 --- a/src/Log/Engine/SentryLog.php +++ b/src/Log/Engine/SentryLog.php @@ -28,6 +28,7 @@ public function __construct(array $config = []) */ public function log($level, $message, array $context = []) { + $context['stackTrace'] = debug_backtrace(); $this->client->capture($level, $message, $context); } } diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 5dc8bf9..18f1e9f 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -198,15 +198,11 @@ public function testCaptureErrorWithErrorLevelInteger(array $mockMethodList): vo } /** - * Test capture error fill breadcrumbs + * Test capture error fill with injected breadcrumbs */ public function testCaptureErrorBuildBreadcrumbs(): void { - $stacks = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT); - $expect = [ - 'file' => $stacks[2]['file'], - 'line' => $stacks[2]['line'], - ]; + $stackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT); $subject = new Client([]); $sentryClientP = $this->prophesize(ClientInterface::class); @@ -216,14 +212,14 @@ public function testCaptureErrorBuildBreadcrumbs(): void Argument::any(), Argument::any(), Argument::any(), - Argument::that(function (EventHint $a) use (&$expect) { - $frames = $a->stacktrace->getFrames(); - $actual = array_slice($frames, -2, 1)[0]; - if ($actual->getFile() !== $expect['file']) { - $this->fail('stacktrace "file" does not t match'); + Argument::that(function (EventHint $actualHint) use ($stackTrace) { + $frames = $actualHint->stacktrace->getFrames(); + $actual = array_pop($frames); + if ($actual->getFile() !== $stackTrace[0]['file']) { + $this->fail('first frame does not match with "file"'); } - if ($actual->getLine() !== $expect['line']) { - $this->fail('stacktrace "line" does not t match'); + if ($actual->getLine() !== $stackTrace[0]['line']) { + $this->fail('first frame does not match with "line"'); } return true; @@ -237,7 +233,7 @@ public function testCaptureErrorBuildBreadcrumbs(): void $subject->getHub()->bindClient($sentryClientP->reveal()); - $subject->capture('warning', 'some error', []); + $subject->capture('warning', 'some error', compact('stackTrace')); } /** diff --git a/tests/TestCase/Log/Engine/SentryLogTest.php b/tests/TestCase/Log/Engine/SentryLogTest.php index 9f5a8a6..872e87d 100644 --- a/tests/TestCase/Log/Engine/SentryLogTest.php +++ b/tests/TestCase/Log/Engine/SentryLogTest.php @@ -45,7 +45,11 @@ public function testLog() $client = $this->getClientProp()->getValue($this->subject); $client->expects($this->once()) ->method('capture') - ->with($level, $message, $context); + ->with( + $level, + $message, + $this->arrayHasKey('stackTrace') + ); $this->subject->log($level, $message, $context); } From 330f6b70a0ede4a4262b051b4b804aa18e5544b6 Mon Sep 17 00:00:00 2001 From: o0h Date: Wed, 12 May 2021 01:13:11 +0900 Subject: [PATCH 37/46] Add an Action to test_app for easy inspection of logging behavior. --- tests/test_app/app/config/routes.php | 1 + .../app/src/Controller/PagesController.php | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/test_app/app/config/routes.php b/tests/test_app/app/config/routes.php index a6bfef3..62a4b9c 100644 --- a/tests/test_app/app/config/routes.php +++ b/tests/test_app/app/config/routes.php @@ -61,6 +61,7 @@ $builder->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']); $builder->connect('/error/*', ['controller' => 'Pages', 'action' => 'error']); $builder->connect('/exception/*', ['controller' => 'Pages', 'action' => 'exception']); + $builder->connect('/log/*', ['controller' => 'Pages', 'action' => 'logging']); }); /* diff --git a/tests/test_app/app/src/Controller/PagesController.php b/tests/test_app/app/src/Controller/PagesController.php index 342dbc3..17664bd 100644 --- a/tests/test_app/app/src/Controller/PagesController.php +++ b/tests/test_app/app/src/Controller/PagesController.php @@ -21,6 +21,7 @@ use Cake\Http\Exception\ForbiddenException; use Cake\Http\Exception\NotFoundException; use Cake\Http\Response; +use Cake\Log\Log; use Cake\Utility\Inflector; use Cake\View\Exception\MissingTemplateException; @@ -88,6 +89,14 @@ public function exception(string $exceptionName, $errorCode = '400') throw new $gottenException($message, $errorCode); } + public function logging(string $errorName) + { + $message = $this->getRequest()->getQuery('message', 'some error'); + $this->doLog($errorName, $message); + + $this->render('dump_vars'); + } + /** * Displays a view * @@ -127,4 +136,10 @@ public function display(...$path): ?Response throw new NotFoundException(); } } + + private function doLog($errorName, string $message) + { + $this->log($message, $errorName, ['contextual data' => 'with hogehoge']); + Log::{$errorName}($message, ['contextual data' => 'with fugafuga']); + } } From 39e116a332949b31a34367293ccbe81039f2a4f2 Mon Sep 17 00:00:00 2001 From: o0h Date: Wed, 12 May 2021 01:30:15 +0900 Subject: [PATCH 38/46] Update required sentry/sdk to 3.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1b09ede..63bbca1 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "require": { "php": "^7.2 || ^8.0", "cakephp/cakephp": "^4.0", - "sentry/sentry": "^3.0" + "sentry/sentry": "^3.2" }, "require-dev": { "cakephp/cakephp-codesniffer": "@stable", From 8a181ab2f85ccd3d4e9b907d55280ab0c4275d88 Mon Sep 17 00:00:00 2001 From: o0h Date: Wed, 12 May 2021 01:11:48 +0900 Subject: [PATCH 39/46] refactor: extract severity conversion logic into private method --- src/Http/Client.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index 5d44431..c9ac467 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -86,11 +86,6 @@ public function capture($level, string $message, array $context): void if ($exception) { $lastEventId = $this->hub->captureException($exception); } else { - if (is_string($level) && method_exists(Severity::class, $level)) { - $severity = (Severity::class . '::' . $level)(); - } else { - $severity = Severity::fromError($level); - } $hint = new EventHint(); $hint->extra = $context; @@ -130,4 +125,19 @@ protected function setupClient(): void $event = new Event('CakeSentry.Client.afterSetup', $this); $this->getEventManager()->dispatch($event); } + + /** + * Convert error info to severity + * + * @param string|int $level Error name or level(int) + * @return \Sentry\Severity + */ + private function convertLevelToSeverity($level): Severity + { + if (is_string($level) && method_exists(Severity::class, $level)) { + return (Severity::class . '::' . $level)(); + } + + return Severity::fromError($level); + } } From 0a41bf547ea86211e94005dcfe6089528db19035 Mon Sep 17 00:00:00 2001 From: o0h Date: Wed, 12 May 2021 01:14:51 +0900 Subject: [PATCH 40/46] refactor: more rigorous testing of beforeSendCallback handling. --- tests/TestCase/Http/ClientTest.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 18f1e9f..21bd7b0 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -7,7 +7,6 @@ use Cake\Event\Event; use Cake\Event\EventManager; use Cake\TestSuite\TestCase; -use Closure; use Connehito\CakeSentry\Http\Client; use Exception; use Prophecy\Argument; @@ -94,6 +93,11 @@ public function testSetupClientSetOptions(): void */ public function testSetupClientSetSendCallback(): void { + $callback = function (\Sentry\Event $event, ?\Sentry\EventHint $hint) { + return 'this is user callback'; + }; + Configure::write('Sentry.before_send', $callback); + $subject = new Client([]); $actual = $subject ->getHub() @@ -101,7 +105,10 @@ public function testSetupClientSetSendCallback(): void ->getOptions() ->getBeforeSendCallback(); - $this->assertInstanceOf(Closure::class, $actual); + $this->assertSame( + $callback(\Sentry\Event::createEvent(), null), + $actual(\Sentry\Event::createEvent(), null) + ); } /** From d12e37d79b6241d320e6c001318549833de50520 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 29 May 2021 19:28:13 +0900 Subject: [PATCH 41/46] Pass the Logger Context when calling capture() --- src/Http/Client.php | 5 ++++- tests/TestCase/Http/ClientTest.php | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index c9ac467..6da5bd7 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -87,7 +87,6 @@ public function capture($level, string $message, array $context): void $lastEventId = $this->hub->captureException($exception); } else { $hint = new EventHint(); - $hint->extra = $context; $stackTrace = $context['stackTrace'] ?? false; if ($stackTrace) { @@ -96,7 +95,11 @@ public function capture($level, string $message, array $context): void $stackTrace[0]['file'], $stackTrace[0]['line'] ); + unset($context['stackTrace']); } + $this->hub->configureScope(function (\Sentry\State\Scope $scope) use ($context) { + $scope->setExtras($context); + }); $severity = $this->convertLevelToSeverity($level); $lastEventId = $this->hub->captureMessage($message, $severity, $hint); diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 21bd7b0..3227fb7 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -243,6 +243,29 @@ public function testCaptureErrorBuildBreadcrumbs(): void $subject->capture('warning', 'some error', compact('stackTrace')); } + /** + * Test capture error pass cakephp-log's context as additional data + */ + public function testCaptureErrorWithAdditionalData(): void + { + $callback = function (\Sentry\Event $event, ?\Sentry\EventHint $hint) use (&$actualEvent) { + $actualEvent = $event; + }; + + $userConfig = [ + 'dsn' => false, + 'before_send' => $callback, + ]; + + Configure::write('Sentry', $userConfig); + $subject = new Client([]); + + $context = ['this is' => 'additional']; + $subject->capture('warning', 'some error', $context); + + $this->assertSame($context, $actualEvent->getExtra()); + } + /** * Check capture dispatch beforeCapture */ From 7780d06a3727f6b3d2e6c375689fdb7789d84c7f Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 29 May 2021 19:35:47 +0900 Subject: [PATCH 42/46] Change the description to consider use cases other than error logs. --- tests/TestCase/Http/ClientTest.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/TestCase/Http/ClientTest.php b/tests/TestCase/Http/ClientTest.php index 3227fb7..b9a8597 100644 --- a/tests/TestCase/Http/ClientTest.php +++ b/tests/TestCase/Http/ClientTest.php @@ -151,11 +151,11 @@ public function testCaptureException(): void } /** - * Test capture error + * Test capture other than exception * * @return array // FIXME: In fact array, but getMethodProphecies declare as MethodProphecy[] */ - public function testCaptureError(): array + public function testCaptureNotHavingException(): array { $subject = new Client([]); $sentryClientP = $this->prophesize(ClientInterface::class); @@ -185,14 +185,14 @@ public function testCaptureError(): array } /** - * Test capture error compatible with the error-level is specified by int or string + * Test capture compatible with the error-level is specified by int or string * - * @depends testCaptureError + * @depends testCaptureNotHavingException * @param array&array $mockMethodList */ - public function testCaptureErrorWithErrorLevelInteger(array $mockMethodList): void + public function testCaptureWithErrorLevelInteger(array $mockMethodList): void { - // Rebuild ObjectProphecy in the same context with testCaptureError. + // Rebuild ObjectProphecy in the same context with testCaptureNotHavingException. $sentryClientP = $this->prophesize(ClientInterface::class); foreach ($mockMethodList as $mockMethod) { $sentryClientP->addMethodProphecy($mockMethod[0]); @@ -205,9 +205,9 @@ public function testCaptureErrorWithErrorLevelInteger(array $mockMethodList): vo } /** - * Test capture error fill with injected breadcrumbs + * Test capture fill with injected breadcrumbs */ - public function testCaptureErrorBuildBreadcrumbs(): void + public function testCaptureBuildBreadcrumbs(): void { $stackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT); @@ -244,9 +244,9 @@ public function testCaptureErrorBuildBreadcrumbs(): void } /** - * Test capture error pass cakephp-log's context as additional data + * Test capture pass cakephp-log's context as additional data */ - public function testCaptureErrorWithAdditionalData(): void + public function testCaptureWithAdditionalData(): void { $callback = function (\Sentry\Event $event, ?\Sentry\EventHint $hint) use (&$actualEvent) { $actualEvent = $event; From a234f00e57c1ef4c0b54558c94fecfb391f563a2 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 29 May 2021 19:35:59 +0900 Subject: [PATCH 43/46] Fix annotation --- src/Http/Client.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Client.php b/src/Http/Client.php index 6da5bd7..1fd858a 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -72,7 +72,7 @@ public function getHub(): Hub /** * Capture exception for sentry. * - * @param mixed $level error level + * @param string|int $level error level * @param string $message error message * @param array $context subject * @return void From df3dc948e3ec8f44ebabdb8c3949335325682ff9 Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 29 May 2021 19:48:21 +0900 Subject: [PATCH 44/46] Fix deprecated phpstan's configuration see: https://phpstan.org/user-guide/discovering-symbols --- phpstan.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon b/phpstan.neon index 78c99ca..061d4ec 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,5 +5,5 @@ parameters: - src - tests/TestCase level: 5 - autoload_files: + bootstrapFiles: - tests/bootstrap.php From 161c6f3b3a44c61daefb7e3168c4bb78a7398a6a Mon Sep 17 00:00:00 2001 From: o0h Date: Sat, 29 May 2021 20:37:24 +0900 Subject: [PATCH 45/46] Update test-app README --- tests/test_app/README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/test_app/README.md b/tests/test_app/README.md index d2088ee..7d22228 100644 --- a/tests/test_app/README.md +++ b/tests/test_app/README.md @@ -16,7 +16,7 @@ Before do it, you must create Sentry PJ and get your DSN. Please check Sentry's document about DSN https://docs.sentry.io/error-reporting/quickstart/?platform=php#configure-the-sdk -1. `cp tests/test_app/app/config/.env.example tests/test_app/app/config/.env`. +1. `cp tests/test_app/app/config/.env.example tests/test_app/app/app.env`. 2. Set your DSN to `.env`. 3. `docker-compose run --rm test-app bash` to go into container. 4. `cd /app/tests/test_app & composer install` if vendor dir is not created. @@ -24,6 +24,9 @@ https://docs.sentry.io/error-reporting/quickstart/?platform=php#configure-the-sd 6. `docker-compose up` to run CakePHP built-in server. 7. Access bellow urls. +### On PHP7 container +You can use `test-app-php7` instead of `test-app`. + ### To check error `http://127.0.0.1:8080/error/:error_level` @@ -49,3 +52,16 @@ Like: If you add `?message` query, then set error message. Like `http://127.0.0.1:8080/exception/method_not_allowed/400?message=you%20cant%20access%20here` + +### To check log +`http://127.0.0.1:8080/log/:log_level_name` + +Replace `:log_level_name` to log level's name. + +Like: + +* http://127.0.0.1:8080/log/info // log message as LOG_INFO +* http://127.0.0.1:8080/log/notice // log message as LOG_NOTICE + +If you add `?message` query, then set error message. +Like `http://127.0.0.1:8080/log/warning?message=some-events-to-logging` From 29cb14f5b2cf26583ec1ded958649cea0e3eb417 Mon Sep 17 00:00:00 2001 From: o0h Date: Mon, 31 May 2021 01:06:03 +0900 Subject: [PATCH 46/46] Update README.md --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a8db06..b2aef9a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ CakePHP integration for Sentry. [![License](https://poser.pugx.org/connehito/cake-sentry/license)](https://packagist.org/packages/connehito/cake-sentry) ## Requirements -- PHP 7.2+ +- PHP 7.2+ / PHP 8.0+ - CakePHP 4.0+ - and [Sentry](https://sentry.io) account @@ -21,6 +21,23 @@ CakePHP integration for Sentry. composer require connehito/cake-sentry:^3.0 ``` +If you do not have the ` php-http/async-client-implementation` package, you will need to install it together. +In that case, you will get a message like the following + +``` +Problem 1 +- sentry/sentry[3.2.0, ... , 3.3.0] require php-http/async-client-implementation ^1.0 -> could not be found in any version, but the following packages provide it: +``` + +Then, you can use the following command to provide a package such as `symfony/http-client`. + +``` +composer require connehito/cake-sentry symfony/http-client +``` + +You can find the available packages on [Packagist](https://packagist.org/providers/php-http/async-client-implementation). + + ## Usage ### Set config files.