From 7d76416ad46b73dd6a31f24362eff4b02a837064 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 5 Dec 2022 12:31:04 +0000 Subject: [PATCH 01/28] Fix events from CLI commands marked handled When a CLI command is run, NunoMaduro\Collision will end up in the backtrace where we expected to find a built-in Laravel or Lumen class This meant the UnhandledState middleware was not correctly marking these events as 'unhandled' The BacktraceProcessor now supports 'NunoMaduro\Collision' as a vendor namespace and so can mark these events as unhandled correctly --- CHANGELOG.md | 7 ++++ src/Internal/BacktraceProcessor.php | 52 +++++++++++++++++++++---- tests/Middleware/UnhandledStateTest.php | 28 +++++++++++++ 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 544a75ad..bd32bd63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ Changelog ========= +## TBD + +### Bug fixes + +* Fix events from CLI commands always being handled when using the `NunoMaduro\Collision` package + [#503](https://github.com/bugsnag/bugsnag-laravel/pull/503) + ## 2.25.0 (2022-10-25) ### Enhancements diff --git a/src/Internal/BacktraceProcessor.php b/src/Internal/BacktraceProcessor.php index 6fc11bce..512f0d7f 100644 --- a/src/Internal/BacktraceProcessor.php +++ b/src/Internal/BacktraceProcessor.php @@ -65,6 +65,7 @@ final class BacktraceProcessor */ const LARAVEL_VENDOR_NAMESPACE = 'Illuminate\\'; const LUMEN_VENDOR_NAMESPACE = 'Laravel\\'; + const COLLISION_VENDOR_NAMESPACE = 'NunoMaduro\\Collision\\'; /** * The current state; one of the self::STATE_ constants. @@ -132,7 +133,7 @@ private function processFrame(array $frame) // if this class is a framework exception handler and the function // matches self::HANDLER_METHOD, we can move on to searching for // the caller - if (($class === self::LARAVEL_HANDLER_CLASS || $class === self::LUMEN_HANDLER_CLASS) + if ($this->isFrameworkExceptionHandler($class) && isset($frame['function']) && $frame['function'] === self::HANDLER_METHOD ) { @@ -144,10 +145,7 @@ private function processFrame(array $frame) case self::STATE_HANDLER_CALLER: // if this is an app exception handler or a framework class, we // can move on to determine if this was unhandled or not - if ($class === self::LARAVEL_APP_EXCEPTION_HANDLER - || $class === self::LUMEN_APP_EXCEPTION_HANDLER - || $this->isVendor($class) - ) { + if ($this->isAppExceptionHandler($class) || $this->isVendor($class)) { $this->state = self::STATE_IS_UNHANDLED; } @@ -180,7 +178,47 @@ private function processFrame(array $frame) */ private function isVendor($class) { - return substr($class, 0, strlen(self::LARAVEL_VENDOR_NAMESPACE)) === self::LARAVEL_VENDOR_NAMESPACE - || substr($class, 0, strlen(self::LUMEN_VENDOR_NAMESPACE)) === self::LUMEN_VENDOR_NAMESPACE; + return $this->isInNamespace($class, self::LARAVEL_VENDOR_NAMESPACE) + || $this->isInNamespace($class, self::LUMEN_VENDOR_NAMESPACE) + || $this->isInNamespace($class, self::COLLISION_VENDOR_NAMESPACE); + } + + /** + * Check if the given class is in the given namespace. + * + * @param string $class + * @param string $namespace + * + * @return bool + */ + private function isInNamespace($class, $namespace) + { + return substr($class, 0, strlen($namespace)) === $namespace; + } + + /** + * Is the given class Laravel or Lumen's exception handler? + * + * @param string $class + * + * @return bool + */ + private function isFrameworkExceptionHandler($class) + { + return $class === self::LARAVEL_HANDLER_CLASS + || $class === self::LUMEN_HANDLER_CLASS; + } + + /** + * Is the given class an App's exception handler? + * + * @param string $class + * + * @return bool + */ + private function isAppExceptionHandler($class) + { + return $class === self::LARAVEL_APP_EXCEPTION_HANDLER + || $class === self::LUMEN_APP_EXCEPTION_HANDLER; } } diff --git a/tests/Middleware/UnhandledStateTest.php b/tests/Middleware/UnhandledStateTest.php index 79b045a6..658538e7 100644 --- a/tests/Middleware/UnhandledStateTest.php +++ b/tests/Middleware/UnhandledStateTest.php @@ -159,6 +159,34 @@ public function unhandledBacktraceProviderLaravel() ['function' => 'z'], ['class' => \Yet\AnotherClass::class], ]]; + + yield 'backtrace with NunoMaduro\\Collision Adapter' => [[ + [ + 'file' => '/app/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php', + 'function' => 'error', + 'class' => 'Illuminate\\Log\\LogManager', + ], + [ + 'file' => '/app/app/Exceptions/Handler.php', + 'function' => 'report', + 'class' => 'Illuminate\\Foundation\\Exceptions\\Handler', + ], + [ + 'file' => '/app/vendor/nunomaduro/collision/src/Adapters/Laravel/ExceptionHandler.php', + 'function' => 'report', + 'class' => 'App\\Exceptions\\Handler', + ], + [ + 'file' => '/app/vendor/laravel/framework/src/Illuminate/Queue/Worker.php', + 'function' => 'report', + 'class' => 'NunoMaduro\\Collision\\Adapters\\Laravel\\ExceptionHandler', + ], + [ + 'file' => '/app/vendor/laravel/framework/src/Illuminate/Queue/Worker.php', + 'function' => 'runJob', + 'class' => 'Illuminate\\Queue\\Worker', + ], + ]]; } public function unhandledBacktraceProviderLumen() From 71065e3150bb02439a0b3251a79d82bbb3ce8642 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 5 Dec 2022 12:23:34 +0000 Subject: [PATCH 02/28] Run queue tests with Laravel 6 --- features/fixtures/docker-compose.yml | 1 + features/fixtures/laravel66/.env | 9 ++--- features/fixtures/laravel66/Dockerfile | 3 ++ .../laravel66/app/Jobs/HandledJob.php | 26 ++++++++++++++ .../laravel66/app/Jobs/UnhandledJob.php | 32 +++++++++++++++++ .../2022_12_05_110544_create_jobs_table.php | 36 +++++++++++++++++++ features/fixtures/laravel66/routes/web.php | 9 +++++ features/queues.feature | 6 ++-- 8 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 features/fixtures/laravel66/app/Jobs/HandledJob.php create mode 100644 features/fixtures/laravel66/app/Jobs/UnhandledJob.php create mode 100644 features/fixtures/laravel66/database/migrations/2022_12_05_110544_create_jobs_table.php diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index bfe17826..8c041775 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -59,6 +59,7 @@ services: published: 61258 laravel66: + init: true build: context: laravel66 args: diff --git a/features/fixtures/laravel66/.env b/features/fixtures/laravel66/.env index ec44a125..63cdf4a9 100644 --- a/features/fixtures/laravel66/.env +++ b/features/fixtures/laravel66/.env @@ -6,18 +6,13 @@ APP_URL=http://localhost LOG_CHANNEL=stack -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=homestead -DB_USERNAME=homestead -DB_PASSWORD=secret +DB_CONNECTION=sqlite BROADCAST_DRIVER=log CACHE_DRIVER=file SESSION_DRIVER=file SESSION_LIFETIME=120 -QUEUE_DRIVER=sync +QUEUE_CONNECTION=database REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null diff --git a/features/fixtures/laravel66/Dockerfile b/features/fixtures/laravel66/Dockerfile index 1f5418c7..614a57a4 100644 --- a/features/fixtures/laravel66/Dockerfile +++ b/features/fixtures/laravel66/Dockerfile @@ -16,4 +16,7 @@ COPY --from=composer:2.2 /usr/bin/composer /usr/local/bin/composer RUN composer install RUN php artisan key:generate +# create database & apply migrations +RUN touch database/database.sqlite && php artisan migrate --no-interaction + CMD php artisan serve --port=8000 --host=0.0.0.0 diff --git a/features/fixtures/laravel66/app/Jobs/HandledJob.php b/features/fixtures/laravel66/app/Jobs/HandledJob.php new file mode 100644 index 00000000..b2abee5b --- /dev/null +++ b/features/fixtures/laravel66/app/Jobs/HandledJob.php @@ -0,0 +1,26 @@ +tries = $tries; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + throw new RuntimeException('uh oh :o'); + } +} diff --git a/features/fixtures/laravel66/database/migrations/2022_12_05_110544_create_jobs_table.php b/features/fixtures/laravel66/database/migrations/2022_12_05_110544_create_jobs_table.php new file mode 100644 index 00000000..1be9e8a8 --- /dev/null +++ b/features/fixtures/laravel66/database/migrations/2022_12_05_110544_create_jobs_table.php @@ -0,0 +1,36 @@ +bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('jobs'); + } +} diff --git a/features/fixtures/laravel66/routes/web.php b/features/fixtures/laravel66/routes/web.php index 805ced2f..93537e3f 100644 --- a/features/fixtures/laravel66/routes/web.php +++ b/features/fixtures/laravel66/routes/web.php @@ -11,6 +11,7 @@ | */ +use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::get('/', function () { @@ -52,6 +53,14 @@ Route::view('/handled_view_exception', 'handledexception'); Route::view('/handled_view_error', 'handlederror'); +Route::get('/queue/unhandled', function (Request $request) { + \App\Jobs\UnhandledJob::dispatch((int) $request->query('tries', '1')); +}); + +Route::get('/queue/handled', function (Request $request) { + \App\Jobs\HandledJob::dispatch(); +}); + /** * Return some diagnostics if an OOM did not happen when it should have. * diff --git a/features/queues.feature b/features/queues.feature index 62cc4192..ca70fc00 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -1,6 +1,6 @@ Feature: Queue support -@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-laravel66 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-lumen8 Scenario: Unhandled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker @@ -21,7 +21,7 @@ Scenario: Unhandled exceptions are delivered from queues And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-laravel66 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts Given I start the laravel fixture And I start the laravel queue worker @@ -78,7 +78,7 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-laravel66 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-lumen8 Scenario: Handled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker From b95d7a18ee65bd6b9411c862fa578d3543c924c0 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 5 Dec 2022 16:28:49 +0000 Subject: [PATCH 03/28] Run queue tests with Laravel 5.8 --- features/fixtures/docker-compose.yml | 1 + features/fixtures/laravel58/.env | 9 ++--- features/fixtures/laravel58/Dockerfile | 3 ++ .../laravel58/app/Jobs/HandledJob.php | 26 ++++++++++++++ .../laravel58/app/Jobs/UnhandledJob.php | 32 +++++++++++++++++ .../2022_12_05_160750_create_jobs_table.php | 36 +++++++++++++++++++ ..._12_05_161039_create_failed_jobs_table.php | 35 ++++++++++++++++++ features/fixtures/laravel58/routes/web.php | 9 +++++ features/queues.feature | 6 ++-- 9 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 features/fixtures/laravel58/app/Jobs/HandledJob.php create mode 100644 features/fixtures/laravel58/app/Jobs/UnhandledJob.php create mode 100644 features/fixtures/laravel58/database/migrations/2022_12_05_160750_create_jobs_table.php create mode 100644 features/fixtures/laravel58/database/migrations/2022_12_05_161039_create_failed_jobs_table.php diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index 8c041775..94a9b3b7 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -40,6 +40,7 @@ services: published: 61256 laravel58: + init: true build: context: laravel58 args: diff --git a/features/fixtures/laravel58/.env b/features/fixtures/laravel58/.env index ec44a125..63cdf4a9 100644 --- a/features/fixtures/laravel58/.env +++ b/features/fixtures/laravel58/.env @@ -6,18 +6,13 @@ APP_URL=http://localhost LOG_CHANNEL=stack -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=homestead -DB_USERNAME=homestead -DB_PASSWORD=secret +DB_CONNECTION=sqlite BROADCAST_DRIVER=log CACHE_DRIVER=file SESSION_DRIVER=file SESSION_LIFETIME=120 -QUEUE_DRIVER=sync +QUEUE_CONNECTION=database REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null diff --git a/features/fixtures/laravel58/Dockerfile b/features/fixtures/laravel58/Dockerfile index 1f5418c7..614a57a4 100644 --- a/features/fixtures/laravel58/Dockerfile +++ b/features/fixtures/laravel58/Dockerfile @@ -16,4 +16,7 @@ COPY --from=composer:2.2 /usr/bin/composer /usr/local/bin/composer RUN composer install RUN php artisan key:generate +# create database & apply migrations +RUN touch database/database.sqlite && php artisan migrate --no-interaction + CMD php artisan serve --port=8000 --host=0.0.0.0 diff --git a/features/fixtures/laravel58/app/Jobs/HandledJob.php b/features/fixtures/laravel58/app/Jobs/HandledJob.php new file mode 100644 index 00000000..0934b767 --- /dev/null +++ b/features/fixtures/laravel58/app/Jobs/HandledJob.php @@ -0,0 +1,26 @@ +tries = $tries; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + throw new RuntimeException('uh oh :o'); + } +} diff --git a/features/fixtures/laravel58/database/migrations/2022_12_05_160750_create_jobs_table.php b/features/fixtures/laravel58/database/migrations/2022_12_05_160750_create_jobs_table.php new file mode 100644 index 00000000..58d77154 --- /dev/null +++ b/features/fixtures/laravel58/database/migrations/2022_12_05_160750_create_jobs_table.php @@ -0,0 +1,36 @@ +bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('jobs'); + } +} diff --git a/features/fixtures/laravel58/database/migrations/2022_12_05_161039_create_failed_jobs_table.php b/features/fixtures/laravel58/database/migrations/2022_12_05_161039_create_failed_jobs_table.php new file mode 100644 index 00000000..d432dff0 --- /dev/null +++ b/features/fixtures/laravel58/database/migrations/2022_12_05_161039_create_failed_jobs_table.php @@ -0,0 +1,35 @@ +bigIncrements('id'); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('failed_jobs'); + } +} diff --git a/features/fixtures/laravel58/routes/web.php b/features/fixtures/laravel58/routes/web.php index 805ced2f..93537e3f 100644 --- a/features/fixtures/laravel58/routes/web.php +++ b/features/fixtures/laravel58/routes/web.php @@ -11,6 +11,7 @@ | */ +use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::get('/', function () { @@ -52,6 +53,14 @@ Route::view('/handled_view_exception', 'handledexception'); Route::view('/handled_view_error', 'handlederror'); +Route::get('/queue/unhandled', function (Request $request) { + \App\Jobs\UnhandledJob::dispatch((int) $request->query('tries', '1')); +}); + +Route::get('/queue/handled', function (Request $request) { + \App\Jobs\HandledJob::dispatch(); +}); + /** * Return some diagnostics if an OOM did not happen when it should have. * diff --git a/features/queues.feature b/features/queues.feature index ca70fc00..305a3ba5 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -1,6 +1,6 @@ Feature: Queue support -@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-laravel56 @not-lumen8 Scenario: Unhandled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker @@ -21,7 +21,7 @@ Scenario: Unhandled exceptions are delivered from queues And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-laravel56 @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts Given I start the laravel fixture And I start the laravel queue worker @@ -78,7 +78,7 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-laravel56 @not-laravel58 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-laravel56 @not-lumen8 Scenario: Handled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker From 0c0b19092731ca93364c64cfef3ff0ecceb354df Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 5 Dec 2022 16:59:58 +0000 Subject: [PATCH 04/28] Run queue tests with Laravel 5.6 --- features/fixtures/laravel56/.env | 9 ++--- features/fixtures/laravel56/Dockerfile | 3 ++ .../laravel56/app/Jobs/HandledJob.php | 26 ++++++++++++++ .../laravel56/app/Jobs/UnhandledJob.php | 32 +++++++++++++++++ .../2022_12_05_165523_create_jobs_table.php | 36 +++++++++++++++++++ ..._12_05_165527_create_failed_jobs_table.php | 35 ++++++++++++++++++ features/fixtures/laravel56/routes/web.php | 9 +++++ features/queues.feature | 6 ++-- 8 files changed, 146 insertions(+), 10 deletions(-) create mode 100644 features/fixtures/laravel56/app/Jobs/HandledJob.php create mode 100644 features/fixtures/laravel56/app/Jobs/UnhandledJob.php create mode 100644 features/fixtures/laravel56/database/migrations/2022_12_05_165523_create_jobs_table.php create mode 100644 features/fixtures/laravel56/database/migrations/2022_12_05_165527_create_failed_jobs_table.php diff --git a/features/fixtures/laravel56/.env b/features/fixtures/laravel56/.env index ec44a125..7e2d4a2a 100644 --- a/features/fixtures/laravel56/.env +++ b/features/fixtures/laravel56/.env @@ -6,18 +6,13 @@ APP_URL=http://localhost LOG_CHANNEL=stack -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=homestead -DB_USERNAME=homestead -DB_PASSWORD=secret +DB_CONNECTION=sqlite BROADCAST_DRIVER=log CACHE_DRIVER=file SESSION_DRIVER=file SESSION_LIFETIME=120 -QUEUE_DRIVER=sync +QUEUE_DRIVER=database REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null diff --git a/features/fixtures/laravel56/Dockerfile b/features/fixtures/laravel56/Dockerfile index 1f5418c7..614a57a4 100644 --- a/features/fixtures/laravel56/Dockerfile +++ b/features/fixtures/laravel56/Dockerfile @@ -16,4 +16,7 @@ COPY --from=composer:2.2 /usr/bin/composer /usr/local/bin/composer RUN composer install RUN php artisan key:generate +# create database & apply migrations +RUN touch database/database.sqlite && php artisan migrate --no-interaction + CMD php artisan serve --port=8000 --host=0.0.0.0 diff --git a/features/fixtures/laravel56/app/Jobs/HandledJob.php b/features/fixtures/laravel56/app/Jobs/HandledJob.php new file mode 100644 index 00000000..0934b767 --- /dev/null +++ b/features/fixtures/laravel56/app/Jobs/HandledJob.php @@ -0,0 +1,26 @@ +tries = $tries; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + throw new RuntimeException('uh oh :o'); + } +} diff --git a/features/fixtures/laravel56/database/migrations/2022_12_05_165523_create_jobs_table.php b/features/fixtures/laravel56/database/migrations/2022_12_05_165523_create_jobs_table.php new file mode 100644 index 00000000..58d77154 --- /dev/null +++ b/features/fixtures/laravel56/database/migrations/2022_12_05_165523_create_jobs_table.php @@ -0,0 +1,36 @@ +bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('jobs'); + } +} diff --git a/features/fixtures/laravel56/database/migrations/2022_12_05_165527_create_failed_jobs_table.php b/features/fixtures/laravel56/database/migrations/2022_12_05_165527_create_failed_jobs_table.php new file mode 100644 index 00000000..d432dff0 --- /dev/null +++ b/features/fixtures/laravel56/database/migrations/2022_12_05_165527_create_failed_jobs_table.php @@ -0,0 +1,35 @@ +bigIncrements('id'); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('failed_jobs'); + } +} diff --git a/features/fixtures/laravel56/routes/web.php b/features/fixtures/laravel56/routes/web.php index 805ced2f..93537e3f 100644 --- a/features/fixtures/laravel56/routes/web.php +++ b/features/fixtures/laravel56/routes/web.php @@ -11,6 +11,7 @@ | */ +use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::get('/', function () { @@ -52,6 +53,14 @@ Route::view('/handled_view_exception', 'handledexception'); Route::view('/handled_view_error', 'handlederror'); +Route::get('/queue/unhandled', function (Request $request) { + \App\Jobs\UnhandledJob::dispatch((int) $request->query('tries', '1')); +}); + +Route::get('/queue/handled', function (Request $request) { + \App\Jobs\HandledJob::dispatch(); +}); + /** * Return some diagnostics if an OOM did not happen when it should have. * diff --git a/features/queues.feature b/features/queues.feature index 305a3ba5..b09737a1 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -1,6 +1,6 @@ Feature: Queue support -@not-laravel-latest @not-laravel51 @not-laravel56 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-lumen8 Scenario: Unhandled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker @@ -21,7 +21,7 @@ Scenario: Unhandled exceptions are delivered from queues And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-laravel56 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts Given I start the laravel fixture And I start the laravel queue worker @@ -78,7 +78,7 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-laravel56 @not-lumen8 +@not-laravel-latest @not-laravel51 @not-lumen8 Scenario: Handled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker From c0b4e14dadf50c72a76a14c2cec2fca7520c0b6e Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 11:31:54 +0000 Subject: [PATCH 05/28] Run queue tests with Laravel 5.1 --- features/fixtures/docker-compose.yml | 1 + features/fixtures/laravel51/.env | 8 +- features/fixtures/laravel51/Dockerfile | 3 + .../fixtures/laravel51/app/Http/routes.php | 8 ++ .../laravel51/app/Jobs/HandledJob.php | 22 +++++ .../laravel51/app/Jobs/UnhandledJob.php | 21 +++++ .../2022_12_06_094153_create_jobs_table.php | 37 +++++++++ ..._12_06_094156_create_failed_jobs_table.php | 33 ++++++++ features/lib/laravel.rb | 25 ++++++ features/queues.feature | 83 ++++++++++--------- features/steps/laravel_steps.rb | 23 ++++- 11 files changed, 218 insertions(+), 46 deletions(-) create mode 100644 features/fixtures/laravel51/app/Jobs/HandledJob.php create mode 100644 features/fixtures/laravel51/app/Jobs/UnhandledJob.php create mode 100644 features/fixtures/laravel51/database/migrations/2022_12_06_094153_create_jobs_table.php create mode 100644 features/fixtures/laravel51/database/migrations/2022_12_06_094156_create_failed_jobs_table.php diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index 94a9b3b7..d7ecbc83 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -2,6 +2,7 @@ version: '3.8' services: laravel51: + init: true build: context: laravel51 args: diff --git a/features/fixtures/laravel51/.env b/features/fixtures/laravel51/.env index cebc8926..cf3794c3 100644 --- a/features/fixtures/laravel51/.env +++ b/features/fixtures/laravel51/.env @@ -2,15 +2,11 @@ APP_ENV=local APP_DEBUG=true APP_KEY=SomeRandomString -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_DATABASE=homestead -DB_USERNAME=homestead -DB_PASSWORD=secret +DB_CONNECTION=sqlite CACHE_DRIVER=file SESSION_DRIVER=file -QUEUE_DRIVER=sync +QUEUE_DRIVER=database REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null diff --git a/features/fixtures/laravel51/Dockerfile b/features/fixtures/laravel51/Dockerfile index c0bba8aa..b5551f8c 100644 --- a/features/fixtures/laravel51/Dockerfile +++ b/features/fixtures/laravel51/Dockerfile @@ -16,4 +16,7 @@ COPY --from=composer:2.2 /usr/bin/composer /usr/local/bin/composer RUN composer install --no-dev RUN php artisan key:generate +# create database & apply migrations +RUN touch database/database.sqlite && php artisan migrate --no-interaction + CMD php artisan serve --port=8000 --host=0.0.0.0 diff --git a/features/fixtures/laravel51/app/Http/routes.php b/features/fixtures/laravel51/app/Http/routes.php index dfc4b2d1..f1e8cbb5 100644 --- a/features/fixtures/laravel51/app/Http/routes.php +++ b/features/fixtures/laravel51/app/Http/routes.php @@ -61,6 +61,14 @@ return view('handlederror'); }); +Route::get('/queue/unhandled', function () { + Queue::push(new \App\Jobs\UnhandledJob()); +}); + +Route::get('/queue/handled', function () { + Queue::push(new \App\Jobs\HandledJob()); +}); + /** * Return some diagnostics if an OOM did not happen when it should have. * diff --git a/features/fixtures/laravel51/app/Jobs/HandledJob.php b/features/fixtures/laravel51/app/Jobs/HandledJob.php new file mode 100644 index 00000000..b706f6d7 --- /dev/null +++ b/features/fixtures/laravel51/app/Jobs/HandledJob.php @@ -0,0 +1,22 @@ +bigIncrements('id'); + $table->string('queue'); + $table->longText('payload'); + $table->tinyInteger('attempts')->unsigned(); + $table->tinyInteger('reserved')->unsigned(); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + $table->index(['queue', 'reserved', 'reserved_at']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('jobs'); + } +} diff --git a/features/fixtures/laravel51/database/migrations/2022_12_06_094156_create_failed_jobs_table.php b/features/fixtures/laravel51/database/migrations/2022_12_06_094156_create_failed_jobs_table.php new file mode 100644 index 00000000..3d733b6b --- /dev/null +++ b/features/fixtures/laravel51/database/migrations/2022_12_06_094156_create_failed_jobs_table.php @@ -0,0 +1,33 @@ +increments('id'); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('failed_jobs'); + } +} diff --git a/features/lib/laravel.rb b/features/lib/laravel.rb index 4f9d6301..a0eb9a91 100644 --- a/features/lib/laravel.rb +++ b/features/lib/laravel.rb @@ -31,6 +31,20 @@ def major_version Integer(/^(?:laravel|lumen)(\d)/.match(fixture)[1]) end + def version + # e.g. laravel56 -> 56, lumen8 -> 8 + raw_digits = /^(?:laravel|lumen)(\d+)/.match(fixture)[1] + + # convert the raw digits to an array of: [major, minor, patch] + # in practice we only have 1 or 2 digits in our fixture names, so fill the + # rest with 0s to make sure Gem::Version doesn't get confused + # e.g. ['5', '6'] -> ['5', '6', '0'], ['8'] -> ['8', '0', '0'] + version_string = raw_digits.chars + version_string.fill("0", version_string.length..2) + + Gem::Version.new(version_string.join(".")) + end + def lumen? fixture.start_with?("lumen") end @@ -46,6 +60,17 @@ def supports_sessions? true end + def queue_worker_command(tries:) + # the command to run the queue worker was 'queue:listen' but changed to + # 'queue:work' in Laravel 5.3 ('queue:work' exists on older Laravels, but + # is not quite equivalent) + if version < '5.3.0' + "php artisan queue:listen --tries=#{tries}" + else + "php artisan queue:work --tries=#{tries}" + end + end + private def load_port_from_docker_compose diff --git a/features/queues.feature b/features/queues.feature index b09737a1..4d58bc9e 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -1,6 +1,6 @@ Feature: Queue support -@not-laravel-latest @not-laravel51 @not-lumen8 +@not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker @@ -9,22 +9,23 @@ Scenario: Unhandled exceptions are delivered from queues Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And the event "metaData.job.queue" equals "default" - And the event "metaData.job.attempts" equals 1 - And the event "metaData.job.connection" equals "database" - And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And the event "app.type" equals "Queue" - And the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" + And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1 + And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" + And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "app.type" equals "Queue" + And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions == 5.1 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-lumen8 +@not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts Given I start the laravel fixture - And I start the laravel queue worker + And I start the laravel queue worker with --tries=3 When I navigate to the route "/queue/unhandled?tries=3" And I wait to receive 3 errors @@ -32,13 +33,14 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And the event "metaData.job.queue" equals "default" - And the event "metaData.job.attempts" equals 1 - And the event "metaData.job.connection" equals "database" - And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And the event "app.type" equals "Queue" - And the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" + And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1 + And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" + And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "app.type" equals "Queue" + And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions == 5.1 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" @@ -49,13 +51,14 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And the event "metaData.job.queue" equals "default" - And the event "metaData.job.attempts" equals 2 - And the event "metaData.job.connection" equals "database" - And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And the event "app.type" equals "Queue" - And the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" + And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 2 + And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" + And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "app.type" equals "Queue" + And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions == 5.1 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" @@ -66,19 +69,20 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And the event "metaData.job.queue" equals "default" - And the event "metaData.job.attempts" equals 3 - And the event "metaData.job.connection" equals "database" - And the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And the event "app.type" equals "Queue" - And the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" + And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 3 + And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" + And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions > 5.1 the event "app.type" equals "Queue" + And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions == 5.1 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" -@not-laravel-latest @not-laravel51 @not-lumen8 +@not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues Given I start the laravel fixture And I start the laravel queue worker @@ -87,13 +91,14 @@ Scenario: Handled exceptions are delivered from queues Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "Exception" And the exception "message" equals "Handled :)" - And the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And the event "metaData.job.queue" equals "default" - And the event "metaData.job.attempts" equals 1 - And the event "metaData.job.connection" equals "database" - And the event "metaData.job.resolved" equals "App\Jobs\HandledJob" - And the event "app.type" equals "Queue" - And the event "context" equals "App\Jobs\HandledJob" + And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" + And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1 + And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" + And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\HandledJob" + And on Laravel versions > 5.1 the event "app.type" equals "Queue" + And on Laravel versions > 5.1 the event "context" equals "App\Jobs\HandledJob" + And on Laravel versions == 5.1 the event "metaData.job" is null And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" diff --git a/features/steps/laravel_steps.rb b/features/steps/laravel_steps.rb index 7777928e..1f44ad7e 100644 --- a/features/steps/laravel_steps.rb +++ b/features/steps/laravel_steps.rb @@ -29,7 +29,11 @@ def exec(service, command, detach: false) end When("I start the laravel queue worker") do - Maze::Docker.exec(Laravel.fixture, "php artisan queue:work", detach: true) + step("I start the laravel queue worker with --tries=1") +end + +When("I start the laravel queue worker with --tries={int}") do |tries| + Maze::Docker.exec(Laravel.fixture, Laravel.queue_worker_command(tries: tries), detach: true) end When("I navigate to the route {string}") do |route| @@ -99,3 +103,20 @@ def exec(service, command, detach: false) step("the session payload field '#{path}' matches the regex '^((\\d+\\.){2}\\d+|\\d\\.x-dev)$'") end + +# conditionally run a step if the laravel version matches a specified version +# +# e.g. this will only check app.type on Laravel 5.2 and above: +# on Laravel versions > 5.1 the event "app.type" equals "Queue" +Then(/^on Laravel versions (>=?|<=?|==) ([0-9.]+) (.*)$/) do |operator, version, step_to_run| + should_run_step = Laravel.version.send(operator, version) + + # make sure this step is debuggable! + $logger.debug("Laravel v#{Laravel.version} #{operator} #{version}? #{should_run_step}") + + if should_run_step + step(step_to_run) + else + $logger.info("Skipping step on Laravel v#{Laravel.version}: #{step_to_run}") + end +end From 1027c7619ba4229613ce09b67a4a536c87947b34 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 12:58:38 +0000 Subject: [PATCH 06/28] Remove 'init: true' from docker compose file This turns out not to be necessary --- features/fixtures/docker-compose.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index d7ecbc83..dad7e282 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -2,7 +2,6 @@ version: '3.8' services: laravel51: - init: true build: context: laravel51 args: @@ -41,7 +40,6 @@ services: published: 61256 laravel58: - init: true build: context: laravel58 args: @@ -61,7 +59,6 @@ services: published: 61258 laravel66: - init: true build: context: laravel66 args: @@ -81,7 +78,6 @@ services: published: 61266 laravel8: - init: true build: context: laravel8 args: @@ -101,7 +97,6 @@ services: published: 61280 laravel9: - init: true build: context: laravel9 args: From dbe6d535d57e8fa1b79ea972894b97f5d225f08b Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 13:00:59 +0000 Subject: [PATCH 07/28] Remove ability to control tries via query string This isn't possible in Laravel 5.1, so we do it in the queue worker command with the '--tries' flag instead --- features/fixtures/laravel56/app/Jobs/UnhandledJob.php | 7 ------- features/fixtures/laravel56/routes/web.php | 7 +++---- features/fixtures/laravel58/app/Jobs/UnhandledJob.php | 7 ------- features/fixtures/laravel58/routes/web.php | 7 +++---- features/fixtures/laravel66/app/Jobs/UnhandledJob.php | 7 ------- features/fixtures/laravel66/routes/web.php | 7 +++---- features/fixtures/laravel8/app/Jobs/UnhandledJob.php | 7 ------- features/fixtures/laravel8/routes/web.php | 9 ++++----- features/fixtures/laravel9/app/Jobs/UnhandledJob.php | 7 ------- features/fixtures/laravel9/routes/web.php | 9 ++++----- features/queues.feature | 2 +- 11 files changed, 18 insertions(+), 58 deletions(-) diff --git a/features/fixtures/laravel56/app/Jobs/UnhandledJob.php b/features/fixtures/laravel56/app/Jobs/UnhandledJob.php index ca4d358c..c71bdd1b 100644 --- a/features/fixtures/laravel56/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel56/app/Jobs/UnhandledJob.php @@ -13,13 +13,6 @@ class UnhandledJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public int $tries; - - public function __construct(int $tries) - { - $this->tries = $tries; - } - /** * Execute the job. * diff --git a/features/fixtures/laravel56/routes/web.php b/features/fixtures/laravel56/routes/web.php index 93537e3f..baa615a1 100644 --- a/features/fixtures/laravel56/routes/web.php +++ b/features/fixtures/laravel56/routes/web.php @@ -11,7 +11,6 @@ | */ -use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::get('/', function () { @@ -53,11 +52,11 @@ Route::view('/handled_view_exception', 'handledexception'); Route::view('/handled_view_error', 'handlederror'); -Route::get('/queue/unhandled', function (Request $request) { - \App\Jobs\UnhandledJob::dispatch((int) $request->query('tries', '1')); +Route::get('/queue/unhandled', function () { + \App\Jobs\UnhandledJob::dispatch(); }); -Route::get('/queue/handled', function (Request $request) { +Route::get('/queue/handled', function () { \App\Jobs\HandledJob::dispatch(); }); diff --git a/features/fixtures/laravel58/app/Jobs/UnhandledJob.php b/features/fixtures/laravel58/app/Jobs/UnhandledJob.php index ca4d358c..c71bdd1b 100644 --- a/features/fixtures/laravel58/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel58/app/Jobs/UnhandledJob.php @@ -13,13 +13,6 @@ class UnhandledJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public int $tries; - - public function __construct(int $tries) - { - $this->tries = $tries; - } - /** * Execute the job. * diff --git a/features/fixtures/laravel58/routes/web.php b/features/fixtures/laravel58/routes/web.php index 93537e3f..baa615a1 100644 --- a/features/fixtures/laravel58/routes/web.php +++ b/features/fixtures/laravel58/routes/web.php @@ -11,7 +11,6 @@ | */ -use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::get('/', function () { @@ -53,11 +52,11 @@ Route::view('/handled_view_exception', 'handledexception'); Route::view('/handled_view_error', 'handlederror'); -Route::get('/queue/unhandled', function (Request $request) { - \App\Jobs\UnhandledJob::dispatch((int) $request->query('tries', '1')); +Route::get('/queue/unhandled', function () { + \App\Jobs\UnhandledJob::dispatch(); }); -Route::get('/queue/handled', function (Request $request) { +Route::get('/queue/handled', function () { \App\Jobs\HandledJob::dispatch(); }); diff --git a/features/fixtures/laravel66/app/Jobs/UnhandledJob.php b/features/fixtures/laravel66/app/Jobs/UnhandledJob.php index 46e6e549..db5ed190 100644 --- a/features/fixtures/laravel66/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel66/app/Jobs/UnhandledJob.php @@ -13,13 +13,6 @@ class UnhandledJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public int $tries; - - public function __construct(int $tries) - { - $this->tries = $tries; - } - /** * Execute the job. * diff --git a/features/fixtures/laravel66/routes/web.php b/features/fixtures/laravel66/routes/web.php index 93537e3f..baa615a1 100644 --- a/features/fixtures/laravel66/routes/web.php +++ b/features/fixtures/laravel66/routes/web.php @@ -11,7 +11,6 @@ | */ -use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::get('/', function () { @@ -53,11 +52,11 @@ Route::view('/handled_view_exception', 'handledexception'); Route::view('/handled_view_error', 'handlederror'); -Route::get('/queue/unhandled', function (Request $request) { - \App\Jobs\UnhandledJob::dispatch((int) $request->query('tries', '1')); +Route::get('/queue/unhandled', function () { + \App\Jobs\UnhandledJob::dispatch(); }); -Route::get('/queue/handled', function (Request $request) { +Route::get('/queue/handled', function () { \App\Jobs\HandledJob::dispatch(); }); diff --git a/features/fixtures/laravel8/app/Jobs/UnhandledJob.php b/features/fixtures/laravel8/app/Jobs/UnhandledJob.php index eb6c9b84..f865c3cc 100644 --- a/features/fixtures/laravel8/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel8/app/Jobs/UnhandledJob.php @@ -14,13 +14,6 @@ class UnhandledJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public int $tries; - - public function __construct(int $tries) - { - $this->tries = $tries; - } - /** * Execute the job. * diff --git a/features/fixtures/laravel8/routes/web.php b/features/fixtures/laravel8/routes/web.php index b7204196..2ebe2765 100644 --- a/features/fixtures/laravel8/routes/web.php +++ b/features/fixtures/laravel8/routes/web.php @@ -1,6 +1,5 @@ query('tries', '1')); +Route::get('/queue/unhandled', function () { + \App\Jobs\UnhandledJob::dispatch(); }); -Route::get('/queue/handled', function (Request $request) { - \App\Jobs\HandledJob::dispatch((int) $request->query('tries', '1')); +Route::get('/queue/handled', function () { + \App\Jobs\HandledJob::dispatch(); }); /** diff --git a/features/fixtures/laravel9/app/Jobs/UnhandledJob.php b/features/fixtures/laravel9/app/Jobs/UnhandledJob.php index eb6c9b84..f865c3cc 100644 --- a/features/fixtures/laravel9/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel9/app/Jobs/UnhandledJob.php @@ -14,13 +14,6 @@ class UnhandledJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public int $tries; - - public function __construct(int $tries) - { - $this->tries = $tries; - } - /** * Execute the job. * diff --git a/features/fixtures/laravel9/routes/web.php b/features/fixtures/laravel9/routes/web.php index b7204196..2ebe2765 100644 --- a/features/fixtures/laravel9/routes/web.php +++ b/features/fixtures/laravel9/routes/web.php @@ -1,6 +1,5 @@ query('tries', '1')); +Route::get('/queue/unhandled', function () { + \App\Jobs\UnhandledJob::dispatch(); }); -Route::get('/queue/handled', function (Request $request) { - \App\Jobs\HandledJob::dispatch((int) $request->query('tries', '1')); +Route::get('/queue/handled', function () { + \App\Jobs\HandledJob::dispatch(); }); /** diff --git a/features/queues.feature b/features/queues.feature index 4d58bc9e..b9f9b8b5 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -26,7 +26,7 @@ Scenario: Unhandled exceptions are delivered from queues Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts Given I start the laravel fixture And I start the laravel queue worker with --tries=3 - When I navigate to the route "/queue/unhandled?tries=3" + When I navigate to the route "/queue/unhandled" And I wait to receive 3 errors # attempt 1 From d70914e1ca73b182eb8850c959a49cc86b12c99f Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 13:02:01 +0000 Subject: [PATCH 08/28] Remove unnecessary script file This was useful when it ran multiple commands (the webserver & queue worker) but is not necessary now that it only runs the webserver --- features/fixtures/laravel9/Dockerfile | 2 +- features/fixtures/laravel9/run-fixture | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100755 features/fixtures/laravel9/run-fixture diff --git a/features/fixtures/laravel9/Dockerfile b/features/fixtures/laravel9/Dockerfile index fcd9bf65..37ae2cdd 100644 --- a/features/fixtures/laravel9/Dockerfile +++ b/features/fixtures/laravel9/Dockerfile @@ -21,4 +21,4 @@ RUN php artisan key:generate # --force is required to create the database RUN php artisan migrate --force --no-interaction -CMD ./run-fixture +CMD php -S 0.0.0.0:8000 -t public diff --git a/features/fixtures/laravel9/run-fixture b/features/fixtures/laravel9/run-fixture deleted file mode 100755 index ea45de3d..00000000 --- a/features/fixtures/laravel9/run-fixture +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# run the PHP webserver -php -S 0.0.0.0:8000 -t public & - -# wait for any process to exit -wait -n - -# exit with the status of the first process to exit -exit $? From 76876ae2fe9f7000eec180ed6f4fbf8b9bf181a3 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 13:02:55 +0000 Subject: [PATCH 09/28] Don't use '--force' when running migrations This doesn't create the database in other Laravel versions and it makes sense for this to be consistent with the other fixtures --- features/fixtures/laravel9/Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/fixtures/laravel9/Dockerfile b/features/fixtures/laravel9/Dockerfile index 37ae2cdd..74e70b99 100644 --- a/features/fixtures/laravel9/Dockerfile +++ b/features/fixtures/laravel9/Dockerfile @@ -17,8 +17,7 @@ RUN cp .env.example .env RUN composer install RUN php artisan key:generate -# apply database migrations -# --force is required to create the database -RUN php artisan migrate --force --no-interaction +# create database & apply migrations +RUN touch database/database.sqlite && php artisan migrate --no-interaction CMD php -S 0.0.0.0:8000 -t public From ee79bceaa0329a77aeb6ee6819506de0c48db37a Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 13:09:01 +0000 Subject: [PATCH 10/28] Don't pretend the database path is configurable The database file is created in the dockerfiles so cannot be changed The Laravel 5.1 fixture is already not configurable --- features/fixtures/laravel56/config/database.php | 2 +- features/fixtures/laravel58/config/database.php | 2 +- features/fixtures/laravel66/config/database.php | 4 ++-- features/fixtures/laravel8/config/database.php | 4 ++-- features/fixtures/laravel9/config/database.php | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/features/fixtures/laravel56/config/database.php b/features/fixtures/laravel56/config/database.php index cab5d068..70633675 100644 --- a/features/fixtures/laravel56/config/database.php +++ b/features/fixtures/laravel56/config/database.php @@ -35,7 +35,7 @@ 'sqlite' => [ 'driver' => 'sqlite', - 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'database' => database_path('database.sqlite'), 'prefix' => '', ], diff --git a/features/fixtures/laravel58/config/database.php b/features/fixtures/laravel58/config/database.php index e92450f9..58a14581 100644 --- a/features/fixtures/laravel58/config/database.php +++ b/features/fixtures/laravel58/config/database.php @@ -35,7 +35,7 @@ 'sqlite' => [ 'driver' => 'sqlite', - 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'database' => database_path('database.sqlite'), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], diff --git a/features/fixtures/laravel66/config/database.php b/features/fixtures/laravel66/config/database.php index 199382d0..0d83af43 100644 --- a/features/fixtures/laravel66/config/database.php +++ b/features/fixtures/laravel66/config/database.php @@ -37,8 +37,8 @@ 'sqlite' => [ 'driver' => 'sqlite', - 'url' => env('DATABASE_URL'), - 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'url' => null, + 'database' => database_path('database.sqlite'), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], diff --git a/features/fixtures/laravel8/config/database.php b/features/fixtures/laravel8/config/database.php index b42d9b30..adfd7351 100644 --- a/features/fixtures/laravel8/config/database.php +++ b/features/fixtures/laravel8/config/database.php @@ -37,8 +37,8 @@ 'sqlite' => [ 'driver' => 'sqlite', - 'url' => env('DATABASE_URL'), - 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'url' => null, + 'database' => database_path('database.sqlite'), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], diff --git a/features/fixtures/laravel9/config/database.php b/features/fixtures/laravel9/config/database.php index dc722b5f..d303ceee 100644 --- a/features/fixtures/laravel9/config/database.php +++ b/features/fixtures/laravel9/config/database.php @@ -37,8 +37,8 @@ 'sqlite' => [ 'driver' => 'sqlite', - 'url' => env('DATABASE_URL'), - 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'url' => null, + 'database' => database_path('database.sqlite'), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], From 1f6c3f66a51e9253ad455244eca36be02e771ce8 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 13:14:52 +0000 Subject: [PATCH 11/28] Implement 'major_version' in terms of 'version' --- features/lib/laravel.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/features/lib/laravel.rb b/features/lib/laravel.rb index a0eb9a91..f2787240 100644 --- a/features/lib/laravel.rb +++ b/features/lib/laravel.rb @@ -27,8 +27,9 @@ def fixture_port end def major_version - # e.g. laravel56 -> 5, lumen8 -> 8 - Integer(/^(?:laravel|lumen)(\d)/.match(fixture)[1]) + # the first "canonical segment" is the first digit of the version number, + # aka the major version + version.canonical_segments.first end def version From 222e9ef889a0ddf2c0f27751393f471e2a5b5f70 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 6 Dec 2022 14:41:12 +0000 Subject: [PATCH 12/28] Read installed Laravel version from the fixture --- features/lib/laravel.rb | 40 ++++++++++++----- features/queues.feature | 80 ++++++++++++++++----------------- features/steps/laravel_steps.rb | 21 +++++++++ 3 files changed, 90 insertions(+), 51 deletions(-) diff --git a/features/lib/laravel.rb b/features/lib/laravel.rb index f2787240..0f68ed85 100644 --- a/features/lib/laravel.rb +++ b/features/lib/laravel.rb @@ -1,5 +1,7 @@ require 'net/http' require 'yaml' +require 'json' +require 'tempfile' class Laravel class << self @@ -33,17 +35,7 @@ def major_version end def version - # e.g. laravel56 -> 56, lumen8 -> 8 - raw_digits = /^(?:laravel|lumen)(\d+)/.match(fixture)[1] - - # convert the raw digits to an array of: [major, minor, patch] - # in practice we only have 1 or 2 digits in our fixture names, so fill the - # rest with 0s to make sure Gem::Version doesn't get confused - # e.g. ['5', '6'] -> ['5', '6', '0'], ['8'] -> ['8', '0', '0'] - version_string = raw_digits.chars - version_string.fill("0", version_string.length..2) - - Gem::Version.new(version_string.join(".")) + @version ||= load_version_from_fixture end def lumen? @@ -80,5 +72,31 @@ def load_port_from_docker_compose service.fetch("ports").first.fetch("published") end + + def load_version_from_fixture + # get and parse the composer.lock file from the fixture + composer_lock = Tempfile.create("#{fixture}-composer.lock") do |file| + # copy the composer lock file out of the fixture so we can read it + Maze::Docker.cp(fixture, source: "/app/composer.lock", destination: file.path) + + # 'file.read' won't reflect the changes made by docker cp, so we use + # JSON.load_file to reload the file & parse it + JSON.load_file(file.path) + end + + framework_section = composer_lock["packages"].find { |package| package["name"] == framework_package_name } + version = framework_section["version"].delete_prefix("v") + + Gem::Version.new(version) + end + + # the composer package name of the framework being used (Lumen or Laravel) + def framework_package_name + if lumen? + "laravel/lumen-framework" + else + "laravel/framework" + end + end end end diff --git a/features/queues.feature b/features/queues.feature index b9f9b8b5..4900ff11 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -9,14 +9,14 @@ Scenario: Unhandled exceptions are delivered from queues Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" - And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1 - And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" - And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions > 5.1 the event "app.type" equals "Queue" - And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions == 5.1 the event "metaData.job" is null + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" @@ -33,14 +33,14 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" - And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1 - And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" - And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions > 5.1 the event "app.type" equals "Queue" - And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions == 5.1 the event "metaData.job" is null + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" @@ -51,14 +51,14 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" - And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 2 - And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" - And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions > 5.1 the event "app.type" equals "Queue" - And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions == 5.1 the event "metaData.job" is null + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 2 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" @@ -69,14 +69,14 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" - And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 3 - And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" - And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions > 5.1 the event "app.type" equals "Queue" - And on Laravel versions > 5.1 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions == 5.1 the event "metaData.job" is null + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 3 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" @@ -91,14 +91,14 @@ Scenario: Handled exceptions are delivered from queues Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "Exception" And the exception "message" equals "Handled :)" - And on Laravel versions > 5.1 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions > 5.1 the event "metaData.job.queue" equals "default" - And on Laravel versions > 5.1 the event "metaData.job.attempts" equals 1 - And on Laravel versions > 5.1 the event "metaData.job.connection" equals "database" - And on Laravel versions > 5.1 the event "metaData.job.resolved" equals "App\Jobs\HandledJob" - And on Laravel versions > 5.1 the event "app.type" equals "Queue" - And on Laravel versions > 5.1 the event "context" equals "App\Jobs\HandledJob" - And on Laravel versions == 5.1 the event "metaData.job" is null + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\HandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\HandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" diff --git a/features/steps/laravel_steps.rb b/features/steps/laravel_steps.rb index 1f44ad7e..10da2d1d 100644 --- a/features/steps/laravel_steps.rb +++ b/features/steps/laravel_steps.rb @@ -24,6 +24,27 @@ def exec(service, command, detach: false) run_docker_compose_command("exec #{flags} #{service} #{command}") end + + def cp(service, source:, destination:) + # cp only exists in 'docker compose' not 'docker-compose', i.e. only + # with a space and not a hyphen + # TODO: can we run all docker compose commands with a space? + run_docker_space_compose_command("cp #{service}:#{source} #{destination}") + end + + private + + def get_docker_space_compose_command(command) + project_name = compose_project_name.nil? ? '' : "-p #{compose_project_name}" + + "docker compose #{project_name} -f #{COMPOSE_FILENAME} #{command}" + end + + def run_docker_space_compose_command(command, success_codes: nil) + command = get_docker_space_compose_command(command) + + @last_command_logs, @last_exit_code = Runner.run_command(command, success_codes: success_codes) + end end end end From 95cc40865fcb32eff2cefb7f94e64267e5ed1dab Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Thu, 8 Dec 2022 14:38:39 +0000 Subject: [PATCH 13/28] Rename scenarios for clarity --- features/queues.feature | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/queues.feature b/features/queues.feature index 4900ff11..cc88fab7 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -1,7 +1,7 @@ Feature: Queue support @not-laravel-latest @not-lumen8 -Scenario: Unhandled exceptions are delivered from queues +Scenario: Unhandled exceptions are delivered from queues when running the queue worker as a daemon Given I start the laravel fixture And I start the laravel queue worker When I navigate to the route "/queue/unhandled" @@ -23,7 +23,7 @@ Scenario: Unhandled exceptions are delivered from queues And the event "severityReason.attributes.framework" equals "Laravel" @not-laravel-latest @not-lumen8 -Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts +Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon Given I start the laravel fixture And I start the laravel queue worker with --tries=3 When I navigate to the route "/queue/unhandled" @@ -83,7 +83,7 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "severityReason.attributes.framework" equals "Laravel" @not-laravel-latest @not-lumen8 -Scenario: Handled exceptions are delivered from queues +Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon Given I start the laravel fixture And I start the laravel queue worker When I navigate to the route "/queue/handled" From e42744372f755baff54856a621c595e73d25166d Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Thu, 8 Dec 2022 15:43:11 +0000 Subject: [PATCH 14/28] Update to Maze Runner v7.9.0 --- Gemfile | 2 +- features/steps/laravel_steps.rb | 26 ++++++-------------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/Gemfile b/Gemfile index 23641092..23e2e699 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,3 @@ source 'https://rubygems.org' -gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v7.6.0' +gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v7.9.0' diff --git a/features/steps/laravel_steps.rb b/features/steps/laravel_steps.rb index 10da2d1d..c1a76b9c 100644 --- a/features/steps/laravel_steps.rb +++ b/features/steps/laravel_steps.rb @@ -14,36 +14,22 @@ } end -# TODO: contribute this back to Maze Runner -# https://github.com/bugsnag/maze-runner/pull/425 module Maze class Docker class << self + # TODO: remove when https://github.com/bugsnag/maze-runner/pull/425 is merged def exec(service, command, detach: false) flags = detach ? "--detach" : "" run_docker_compose_command("exec #{flags} #{service} #{command}") end + # TODO: contribute this back to Maze Runner + # probably need a nicer API, capable of doing a copy in either + # direction (right now this can only copy from the service to the + # local machine) def cp(service, source:, destination:) - # cp only exists in 'docker compose' not 'docker-compose', i.e. only - # with a space and not a hyphen - # TODO: can we run all docker compose commands with a space? - run_docker_space_compose_command("cp #{service}:#{source} #{destination}") - end - - private - - def get_docker_space_compose_command(command) - project_name = compose_project_name.nil? ? '' : "-p #{compose_project_name}" - - "docker compose #{project_name} -f #{COMPOSE_FILENAME} #{command}" - end - - def run_docker_space_compose_command(command, success_codes: nil) - command = get_docker_space_compose_command(command) - - @last_command_logs, @last_exit_code = Runner.run_command(command, success_codes: success_codes) + run_docker_compose_command("cp #{service}:#{source} #{destination}") end end end From 407418ae15853de0688337af6a8a7fc9c7da6532 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Thu, 8 Dec 2022 15:06:44 +0000 Subject: [PATCH 15/28] Add tests with non-daemonised queue worker --- features/lib/laravel.rb | 14 +++- features/queues.feature | 110 ++++++++++++++++++++++++++++++++ features/steps/laravel_steps.rb | 10 ++- 3 files changed, 131 insertions(+), 3 deletions(-) diff --git a/features/lib/laravel.rb b/features/lib/laravel.rb index 0f68ed85..a9066191 100644 --- a/features/lib/laravel.rb +++ b/features/lib/laravel.rb @@ -53,11 +53,21 @@ def supports_sessions? true end - def queue_worker_command(tries:) + # the command to run the queue worker for a single job + def queue_worker_once_command(tries) + if version < "5.3.0" + "php artisan queue:work --tries=#{tries}" + else + "php artisan queue:work --once --tries=#{tries}" + end + end + + # the command to run the queue worker as a daemon + def queue_worker_daemon_command(tries) # the command to run the queue worker was 'queue:listen' but changed to # 'queue:work' in Laravel 5.3 ('queue:work' exists on older Laravels, but # is not quite equivalent) - if version < '5.3.0' + if version < "5.3.0" "php artisan queue:listen --tries=#{tries}" else "php artisan queue:work --tries=#{tries}" diff --git a/features/queues.feature b/features/queues.feature index cc88fab7..fe0ff7f2 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -102,3 +102,113 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" + +@not-laravel-latest @not-lumen8 +Scenario: Unhandled exceptions are delivered from queues when running the queue worker once + Given I start the laravel fixture + When I navigate to the route "/queue/unhandled" + Then I should receive no errors + When I run the laravel queue worker + And I wait to receive an error + Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier + And the exception "errorClass" equals "RuntimeException" + And the exception "message" equals "uh oh :o" + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null + And the event "severity" equals "error" + And the event "unhandled" is true + And the event "severityReason.type" equals "unhandledExceptionMiddleware" + And the event "severityReason.attributes.framework" equals "Laravel" + +@not-laravel-latest @not-lumen8 +Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon + Given I start the laravel fixture + When I navigate to the route "/queue/unhandled" + Then I should receive no errors + + # attempt 1 + When I run the laravel queue worker with --tries=3 + And I wait to receive an error + Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier + And the exception "errorClass" equals "RuntimeException" + And the exception "message" equals "uh oh :o" + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null + And the event "severity" equals "error" + And the event "unhandled" is true + And the event "severityReason.type" equals "unhandledExceptionMiddleware" + And the event "severityReason.attributes.framework" equals "Laravel" + + # attempt 2 + When I discard the oldest error + And I run the laravel queue worker with --tries=3 + And I wait to receive an error + Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier + And the exception "errorClass" equals "RuntimeException" + And the exception "message" equals "uh oh :o" + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 2 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null + And the event "severity" equals "error" + And the event "unhandled" is true + And the event "severityReason.type" equals "unhandledExceptionMiddleware" + And the event "severityReason.attributes.framework" equals "Laravel" + + # attempt 3 + When I discard the oldest error + And I run the laravel queue worker with --tries=3 + And I wait to receive an error + Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier + And the exception "errorClass" equals "RuntimeException" + And the exception "message" equals "uh oh :o" + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 3 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null + And the event "severity" equals "error" + And the event "unhandled" is true + And the event "severityReason.type" equals "unhandledExceptionMiddleware" + And the event "severityReason.attributes.framework" equals "Laravel" + +@not-laravel-latest @not-lumen8 +Scenario: Handled exceptions are delivered from queues when running the queue worker once + Given I start the laravel fixture + When I navigate to the route "/queue/handled" + Then I should receive no errors + When I run the laravel queue worker + And I wait to receive an error + Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier + And the exception "errorClass" equals "Exception" + And the exception "message" equals "Handled :)" + And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" + And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 + And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" + And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\HandledJob" + And on Laravel versions >= 5.2 the event "app.type" equals "Queue" + And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\HandledJob" + And on Laravel versions < 5.2 the event "metaData.job" is null + And the event "severity" equals "warning" + And the event "unhandled" is false + And the event "severityReason.type" equals "handledException" diff --git a/features/steps/laravel_steps.rb b/features/steps/laravel_steps.rb index c1a76b9c..e605f55d 100644 --- a/features/steps/laravel_steps.rb +++ b/features/steps/laravel_steps.rb @@ -40,7 +40,15 @@ def cp(service, source:, destination:) end When("I start the laravel queue worker with --tries={int}") do |tries| - Maze::Docker.exec(Laravel.fixture, Laravel.queue_worker_command(tries: tries), detach: true) + Maze::Docker.exec(Laravel.fixture, Laravel.queue_worker_daemon_command(tries), detach: true) +end + +When("I run the laravel queue worker") do + step("I run the laravel queue worker with --tries=1") +end + +When("I run the laravel queue worker with --tries={int}") do |tries| + Maze::Docker.exec(Laravel.fixture, Laravel.queue_worker_once_command(tries)) end When("I navigate to the route {string}") do |route| From eb948a6731fd21007a7c30d1bbdd2bdc83337625 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 10:08:23 +0000 Subject: [PATCH 16/28] Fix scenario name --- features/queues.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/queues.feature b/features/queues.feature index fe0ff7f2..a85c1c4c 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -127,7 +127,7 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "severityReason.attributes.framework" equals "Laravel" @not-laravel-latest @not-lumen8 -Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon +Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once Given I start the laravel fixture When I navigate to the route "/queue/unhandled" Then I should receive no errors From 742c16ddd764d4a943c729e9b4289894450f7a14 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 10:09:48 +0000 Subject: [PATCH 17/28] Assert against the number of breadcrumbs in events --- features/fixtures/docker-compose.yml | 1 + .../fixtures/laravel9/app/Jobs/HandledJob.php | 2 + .../laravel9/app/Jobs/UnhandledJob.php | 3 ++ .../app/Providers/AppServiceProvider.php | 3 +- .../app/Providers/EventServiceProvider.php | 17 ++++++- features/queues.feature | 48 +++++++++++++++++++ features/steps/laravel_steps.rb | 20 ++++++++ 7 files changed, 92 insertions(+), 2 deletions(-) diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index dad7e282..9a2a7006 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -110,6 +110,7 @@ services: - BUGSNAG_REGISTER_OOM_BOOTSTRAPPER - BUGSNAG_DISCARD_CLASSES - BUGSNAG_REDACTED_KEYS + - BUGSNAG_QUERY restart: "no" ports: - target: 8000 diff --git a/features/fixtures/laravel9/app/Jobs/HandledJob.php b/features/fixtures/laravel9/app/Jobs/HandledJob.php index 587677d3..0ba9744f 100644 --- a/features/fixtures/laravel9/app/Jobs/HandledJob.php +++ b/features/fixtures/laravel9/app/Jobs/HandledJob.php @@ -22,6 +22,8 @@ class HandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + Bugsnag::notifyException(new Exception('Handled :)')); } } diff --git a/features/fixtures/laravel9/app/Jobs/UnhandledJob.php b/features/fixtures/laravel9/app/Jobs/UnhandledJob.php index f865c3cc..c443e886 100644 --- a/features/fixtures/laravel9/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel9/app/Jobs/UnhandledJob.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; @@ -21,6 +22,8 @@ class UnhandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + throw new RuntimeException('uh oh :o'); } } diff --git a/features/fixtures/laravel9/app/Providers/AppServiceProvider.php b/features/fixtures/laravel9/app/Providers/AppServiceProvider.php index 49823ec1..8c5de890 100644 --- a/features/fixtures/laravel9/app/Providers/AppServiceProvider.php +++ b/features/fixtures/laravel9/app/Providers/AppServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class AppServiceProvider extends ServiceProvider { @@ -34,6 +35,6 @@ public function register() */ public function boot() { - // + Bugsnag::leaveBreadcrumb(__METHOD__); } } diff --git a/features/fixtures/laravel9/app/Providers/EventServiceProvider.php b/features/fixtures/laravel9/app/Providers/EventServiceProvider.php index 23499eb8..1e181fb4 100644 --- a/features/fixtures/laravel9/app/Providers/EventServiceProvider.php +++ b/features/fixtures/laravel9/app/Providers/EventServiceProvider.php @@ -6,6 +6,11 @@ use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Queue; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; +use Illuminate\Queue\Events\JobProcessing; +use Illuminate\Queue\Events\JobProcessed; +use Illuminate\Queue\Events\JobExceptionOccurred; class EventServiceProvider extends ServiceProvider { @@ -27,6 +32,16 @@ class EventServiceProvider extends ServiceProvider */ public function boot() { - // + Queue::before(function (JobProcessing $event) { + Bugsnag::leaveBreadcrumb('before'); + }); + + Queue::after(function (JobProcessed $event) { + Bugsnag::leaveBreadcrumb('after'); + }); + + Queue::exceptionOccurred(function (JobExceptionOccurred $event) { + Bugsnag::leaveBreadcrumb('exceptionOccurred'); + }); } } diff --git a/features/queues.feature b/features/queues.feature index a85c1c4c..fb706ea7 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -1,5 +1,10 @@ Feature: Queue support +Background: + # disable automatic query breadcrumbs as we assert against the specific number + # of breadcrumbs in these tests + Given I set environment variable "BUGSNAG_QUERY" to "false" + @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker as a daemon Given I start the laravel fixture @@ -21,6 +26,10 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon @@ -45,6 +54,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 3 breadcrumbs # attempt 2 When I discard the oldest error @@ -63,6 +76,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 3 breadcrumbs # attempt 3 When I discard the oldest error @@ -81,6 +98,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon @@ -102,6 +123,9 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 9.0 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker once @@ -125,6 +149,11 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once @@ -150,6 +179,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 4 breadcrumbs # attempt 2 When I discard the oldest error @@ -170,6 +204,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 4 breadcrumbs # attempt 3 When I discard the oldest error @@ -190,6 +229,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 9.0 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker once @@ -212,3 +256,7 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 9.0 the event has 3 breadcrumbs diff --git a/features/steps/laravel_steps.rb b/features/steps/laravel_steps.rb index e605f55d..23823baf 100644 --- a/features/steps/laravel_steps.rb +++ b/features/steps/laravel_steps.rb @@ -119,6 +119,26 @@ def cp(service, source:, destination:) step("the session payload field '#{path}' matches the regex '^((\\d+\\.){2}\\d+|\\d\\.x-dev)$'") end +# TODO: remove when https://github.com/bugsnag/maze-runner/pull/433 is released +Then("the event has {int} breadcrumb(s)") do |expected| + breadcrumbs = Maze::Server.errors.current[:body]['events'].first['breadcrumbs'] + + Maze.check.equal( + expected, + breadcrumbs.length, + "Expected event to have '#{expected}' breadcrumbs, but got: #{breadcrumbs}" + ) +end + +Then("the event has no breadcrumbs") do + breadcrumbs = Maze::Server.errors.current[:body]['events'].first['breadcrumbs'] + + Maze.check.true( + breadcrumbs.nil? || breadcrumbs.empty?, + "Expected event not to have breadcrumbs, but got: #{breadcrumbs}" + ) +end + # conditionally run a step if the laravel version matches a specified version # # e.g. this will only check app.type on Laravel 5.2 and above: From b05d848de60d567a67c71c5eebcfdc9b38b5042c Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 10:00:19 +0000 Subject: [PATCH 18/28] Test breadcrumbs in queues on Laravel 8 --- features/fixtures/docker-compose.yml | 1 + .../fixtures/laravel8/app/Jobs/HandledJob.php | 2 + .../laravel8/app/Jobs/UnhandledJob.php | 3 + .../app/Providers/AppServiceProvider.php | 3 +- .../app/Providers/EventServiceProvider.php | 17 +++- features/queues.feature | 86 +++++++++---------- 6 files changed, 67 insertions(+), 45 deletions(-) diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index 9a2a7006..692a4b28 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -91,6 +91,7 @@ services: - BUGSNAG_REGISTER_OOM_BOOTSTRAPPER - BUGSNAG_DISCARD_CLASSES - BUGSNAG_REDACTED_KEYS + - BUGSNAG_QUERY restart: "no" ports: - target: 8000 diff --git a/features/fixtures/laravel8/app/Jobs/HandledJob.php b/features/fixtures/laravel8/app/Jobs/HandledJob.php index 587677d3..0ba9744f 100644 --- a/features/fixtures/laravel8/app/Jobs/HandledJob.php +++ b/features/fixtures/laravel8/app/Jobs/HandledJob.php @@ -22,6 +22,8 @@ class HandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + Bugsnag::notifyException(new Exception('Handled :)')); } } diff --git a/features/fixtures/laravel8/app/Jobs/UnhandledJob.php b/features/fixtures/laravel8/app/Jobs/UnhandledJob.php index f865c3cc..c443e886 100644 --- a/features/fixtures/laravel8/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel8/app/Jobs/UnhandledJob.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; @@ -21,6 +22,8 @@ class UnhandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + throw new RuntimeException('uh oh :o'); } } diff --git a/features/fixtures/laravel8/app/Providers/AppServiceProvider.php b/features/fixtures/laravel8/app/Providers/AppServiceProvider.php index 49823ec1..8c5de890 100644 --- a/features/fixtures/laravel8/app/Providers/AppServiceProvider.php +++ b/features/fixtures/laravel8/app/Providers/AppServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class AppServiceProvider extends ServiceProvider { @@ -34,6 +35,6 @@ public function register() */ public function boot() { - // + Bugsnag::leaveBreadcrumb(__METHOD__); } } diff --git a/features/fixtures/laravel8/app/Providers/EventServiceProvider.php b/features/fixtures/laravel8/app/Providers/EventServiceProvider.php index a9f10a63..a6a22d3d 100644 --- a/features/fixtures/laravel8/app/Providers/EventServiceProvider.php +++ b/features/fixtures/laravel8/app/Providers/EventServiceProvider.php @@ -6,6 +6,11 @@ use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Queue; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; +use Illuminate\Queue\Events\JobProcessing; +use Illuminate\Queue\Events\JobProcessed; +use Illuminate\Queue\Events\JobExceptionOccurred; class EventServiceProvider extends ServiceProvider { @@ -27,6 +32,16 @@ class EventServiceProvider extends ServiceProvider */ public function boot() { - // + Queue::before(function (JobProcessing $event) { + Bugsnag::leaveBreadcrumb('before'); + }); + + Queue::after(function (JobProcessed $event) { + Bugsnag::leaveBreadcrumb('after'); + }); + + Queue::exceptionOccurred(function (JobExceptionOccurred $event) { + Bugsnag::leaveBreadcrumb('exceptionOccurred'); + }); } } diff --git a/features/queues.feature b/features/queues.feature index fb706ea7..e90992cb 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -26,10 +26,10 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 3 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon @@ -54,10 +54,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 3 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 3 breadcrumbs # attempt 2 When I discard the oldest error @@ -76,10 +76,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 3 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 3 breadcrumbs # attempt 3 When I discard the oldest error @@ -98,10 +98,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 3 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon @@ -123,9 +123,9 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 9.0 the event has 2 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 8.0 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker once @@ -149,11 +149,11 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 4 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once @@ -179,11 +179,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 4 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 4 breadcrumbs # attempt 2 When I discard the oldest error @@ -204,11 +204,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 4 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 4 breadcrumbs # attempt 3 When I discard the oldest error @@ -229,11 +229,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 9.0 the event has 4 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 8.0 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker once @@ -256,7 +256,7 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 9.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 9.0 the event has 3 breadcrumbs + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 8.0 the event has 3 breadcrumbs From 1a5a168127b7972042bced2e387e94a7090d1483 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 10:31:32 +0000 Subject: [PATCH 19/28] Test breadcrumbs in queues on Laravel 6 --- features/fixtures/docker-compose.yml | 1 + .../laravel66/app/Jobs/HandledJob.php | 2 + .../laravel66/app/Jobs/UnhandledJob.php | 3 + .../app/Providers/AppServiceProvider.php | 3 +- .../app/Providers/EventServiceProvider.php | 17 +++- features/queues.feature | 86 +++++++++---------- 6 files changed, 66 insertions(+), 46 deletions(-) diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index 692a4b28..b545d88f 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -72,6 +72,7 @@ services: - BUGSNAG_REGISTER_OOM_BOOTSTRAPPER - BUGSNAG_DISCARD_CLASSES - BUGSNAG_REDACTED_KEYS + - BUGSNAG_QUERY restart: "no" ports: - target: 8000 diff --git a/features/fixtures/laravel66/app/Jobs/HandledJob.php b/features/fixtures/laravel66/app/Jobs/HandledJob.php index b2abee5b..ec101a25 100644 --- a/features/fixtures/laravel66/app/Jobs/HandledJob.php +++ b/features/fixtures/laravel66/app/Jobs/HandledJob.php @@ -21,6 +21,8 @@ class HandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + Bugsnag::notifyException(new Exception('Handled :)')); } } diff --git a/features/fixtures/laravel66/app/Jobs/UnhandledJob.php b/features/fixtures/laravel66/app/Jobs/UnhandledJob.php index db5ed190..464b82cb 100644 --- a/features/fixtures/laravel66/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel66/app/Jobs/UnhandledJob.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; @@ -20,6 +21,8 @@ class UnhandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + throw new RuntimeException('uh oh :o'); } } diff --git a/features/fixtures/laravel66/app/Providers/AppServiceProvider.php b/features/fixtures/laravel66/app/Providers/AppServiceProvider.php index 49823ec1..8c5de890 100644 --- a/features/fixtures/laravel66/app/Providers/AppServiceProvider.php +++ b/features/fixtures/laravel66/app/Providers/AppServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class AppServiceProvider extends ServiceProvider { @@ -34,6 +35,6 @@ public function register() */ public function boot() { - // + Bugsnag::leaveBreadcrumb(__METHOD__); } } diff --git a/features/fixtures/laravel66/app/Providers/EventServiceProvider.php b/features/fixtures/laravel66/app/Providers/EventServiceProvider.php index 723a290d..a6a22d3d 100644 --- a/features/fixtures/laravel66/app/Providers/EventServiceProvider.php +++ b/features/fixtures/laravel66/app/Providers/EventServiceProvider.php @@ -6,6 +6,11 @@ use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Queue; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; +use Illuminate\Queue\Events\JobProcessing; +use Illuminate\Queue\Events\JobProcessed; +use Illuminate\Queue\Events\JobExceptionOccurred; class EventServiceProvider extends ServiceProvider { @@ -27,8 +32,16 @@ class EventServiceProvider extends ServiceProvider */ public function boot() { - parent::boot(); + Queue::before(function (JobProcessing $event) { + Bugsnag::leaveBreadcrumb('before'); + }); - // + Queue::after(function (JobProcessed $event) { + Bugsnag::leaveBreadcrumb('after'); + }); + + Queue::exceptionOccurred(function (JobExceptionOccurred $event) { + Bugsnag::leaveBreadcrumb('exceptionOccurred'); + }); } } diff --git a/features/queues.feature b/features/queues.feature index e90992cb..9acd6717 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -26,10 +26,10 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 3 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon @@ -54,10 +54,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 3 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 3 breadcrumbs # attempt 2 When I discard the oldest error @@ -76,10 +76,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 3 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 3 breadcrumbs # attempt 3 When I discard the oldest error @@ -98,10 +98,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 3 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon @@ -123,9 +123,9 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 8.0 the event has 2 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 6.0 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker once @@ -149,11 +149,11 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 4 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once @@ -179,11 +179,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 4 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 4 breadcrumbs # attempt 2 When I discard the oldest error @@ -204,11 +204,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 4 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 4 breadcrumbs # attempt 3 When I discard the oldest error @@ -229,11 +229,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 8.0 the event has 4 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 6.0 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker once @@ -256,7 +256,7 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 8.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 8.0 the event has 3 breadcrumbs + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 6.0 the event has 3 breadcrumbs From f57f5f68bcdf507201aae33473bf2691a7028e26 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 10:55:16 +0000 Subject: [PATCH 20/28] Test breadcrumbs in queues on Laravel 5.8 --- features/fixtures/docker-compose.yml | 1 + .../laravel58/app/Jobs/HandledJob.php | 2 + .../laravel58/app/Jobs/UnhandledJob.php | 3 + .../app/Providers/AppServiceProvider.php | 3 +- .../app/Providers/EventServiceProvider.php | 17 +++- features/queues.feature | 86 +++++++++---------- 6 files changed, 66 insertions(+), 46 deletions(-) diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index b545d88f..03d402ce 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -53,6 +53,7 @@ services: - BUGSNAG_REGISTER_OOM_BOOTSTRAPPER - BUGSNAG_DISCARD_CLASSES - BUGSNAG_REDACTED_KEYS + - BUGSNAG_QUERY restart: "no" ports: - target: 8000 diff --git a/features/fixtures/laravel58/app/Jobs/HandledJob.php b/features/fixtures/laravel58/app/Jobs/HandledJob.php index 0934b767..f29ab2f3 100644 --- a/features/fixtures/laravel58/app/Jobs/HandledJob.php +++ b/features/fixtures/laravel58/app/Jobs/HandledJob.php @@ -21,6 +21,8 @@ class HandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + Bugsnag::notifyException(new Exception('Handled :)')); } } diff --git a/features/fixtures/laravel58/app/Jobs/UnhandledJob.php b/features/fixtures/laravel58/app/Jobs/UnhandledJob.php index c71bdd1b..91db78fb 100644 --- a/features/fixtures/laravel58/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel58/app/Jobs/UnhandledJob.php @@ -2,6 +2,7 @@ namespace App\Jobs; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; use RuntimeException; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; @@ -20,6 +21,8 @@ class UnhandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + throw new RuntimeException('uh oh :o'); } } diff --git a/features/fixtures/laravel58/app/Providers/AppServiceProvider.php b/features/fixtures/laravel58/app/Providers/AppServiceProvider.php index 49823ec1..8c5de890 100644 --- a/features/fixtures/laravel58/app/Providers/AppServiceProvider.php +++ b/features/fixtures/laravel58/app/Providers/AppServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class AppServiceProvider extends ServiceProvider { @@ -34,6 +35,6 @@ public function register() */ public function boot() { - // + Bugsnag::leaveBreadcrumb(__METHOD__); } } diff --git a/features/fixtures/laravel58/app/Providers/EventServiceProvider.php b/features/fixtures/laravel58/app/Providers/EventServiceProvider.php index 6c64e52b..781ef6a1 100644 --- a/features/fixtures/laravel58/app/Providers/EventServiceProvider.php +++ b/features/fixtures/laravel58/app/Providers/EventServiceProvider.php @@ -6,6 +6,11 @@ use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use Illuminate\Support\Facades\Queue; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; +use Illuminate\Queue\Events\JobProcessing; +use Illuminate\Queue\Events\JobProcessed; +use Illuminate\Queue\Events\JobExceptionOccurred; class EventServiceProvider extends ServiceProvider { @@ -27,8 +32,16 @@ class EventServiceProvider extends ServiceProvider */ public function boot() { - parent::boot(); + Queue::before(function (JobProcessing $event) { + Bugsnag::leaveBreadcrumb('before'); + }); - // + Queue::after(function (JobProcessed $event) { + Bugsnag::leaveBreadcrumb('after'); + }); + + Queue::exceptionOccurred(function (JobExceptionOccurred $event) { + Bugsnag::leaveBreadcrumb('exceptionOccurred'); + }); } } diff --git a/features/queues.feature b/features/queues.feature index 9acd6717..53ed0413 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -26,10 +26,10 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 3 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon @@ -54,10 +54,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 3 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 3 breadcrumbs # attempt 2 When I discard the oldest error @@ -76,10 +76,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 3 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 3 breadcrumbs # attempt 3 When I discard the oldest error @@ -98,10 +98,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 3 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon @@ -123,9 +123,9 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 6.0 the event has 2 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 5.8 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker once @@ -149,11 +149,11 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 4 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once @@ -179,11 +179,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 4 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 4 breadcrumbs # attempt 2 When I discard the oldest error @@ -204,11 +204,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 4 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 4 breadcrumbs # attempt 3 When I discard the oldest error @@ -229,11 +229,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 6.0 the event has 4 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.8 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker once @@ -256,7 +256,7 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 6.0 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 6.0 the event has 3 breadcrumbs + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 5.8 the event has 3 breadcrumbs From 03bf7de1aa3823da8ddfaf7d6e8a2924f3de6286 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 12:07:16 +0000 Subject: [PATCH 21/28] Test breadcrumbs in queues on Laravel 5.6 --- features/fixtures/docker-compose.yml | 1 + .../laravel56/app/Jobs/HandledJob.php | 2 + .../laravel56/app/Jobs/UnhandledJob.php | 3 + .../app/Providers/AppServiceProvider.php | 3 +- .../app/Providers/EventServiceProvider.php | 17 +++- features/queues.feature | 86 +++++++++---------- 6 files changed, 67 insertions(+), 45 deletions(-) diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index 03d402ce..c2b5cc3d 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -34,6 +34,7 @@ services: - BUGSNAG_REGISTER_OOM_BOOTSTRAPPER - BUGSNAG_DISCARD_CLASSES - BUGSNAG_REDACTED_KEYS + - BUGSNAG_QUERY restart: "no" ports: - target: 8000 diff --git a/features/fixtures/laravel56/app/Jobs/HandledJob.php b/features/fixtures/laravel56/app/Jobs/HandledJob.php index 0934b767..f29ab2f3 100644 --- a/features/fixtures/laravel56/app/Jobs/HandledJob.php +++ b/features/fixtures/laravel56/app/Jobs/HandledJob.php @@ -21,6 +21,8 @@ class HandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + Bugsnag::notifyException(new Exception('Handled :)')); } } diff --git a/features/fixtures/laravel56/app/Jobs/UnhandledJob.php b/features/fixtures/laravel56/app/Jobs/UnhandledJob.php index c71bdd1b..d8ad29b8 100644 --- a/features/fixtures/laravel56/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel56/app/Jobs/UnhandledJob.php @@ -8,6 +8,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class UnhandledJob implements ShouldQueue { @@ -20,6 +21,8 @@ class UnhandledJob implements ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + throw new RuntimeException('uh oh :o'); } } diff --git a/features/fixtures/laravel56/app/Providers/AppServiceProvider.php b/features/fixtures/laravel56/app/Providers/AppServiceProvider.php index 85ea7198..74755cf6 100644 --- a/features/fixtures/laravel56/app/Providers/AppServiceProvider.php +++ b/features/fixtures/laravel56/app/Providers/AppServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class AppServiceProvider extends ServiceProvider { @@ -13,7 +14,7 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { - // + Bugsnag::leaveBreadcrumb(__METHOD__); } /** diff --git a/features/fixtures/laravel56/app/Providers/EventServiceProvider.php b/features/fixtures/laravel56/app/Providers/EventServiceProvider.php index f106ba4d..5a41faab 100644 --- a/features/fixtures/laravel56/app/Providers/EventServiceProvider.php +++ b/features/fixtures/laravel56/app/Providers/EventServiceProvider.php @@ -4,6 +4,11 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Queue; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; +use Illuminate\Queue\Events\JobProcessing; +use Illuminate\Queue\Events\JobProcessed; +use Illuminate\Queue\Events\JobExceptionOccurred; class EventServiceProvider extends ServiceProvider { @@ -27,6 +32,16 @@ public function boot() { parent::boot(); - // + Queue::before(function (JobProcessing $event) { + Bugsnag::leaveBreadcrumb('before'); + }); + + Queue::after(function (JobProcessed $event) { + Bugsnag::leaveBreadcrumb('after'); + }); + + Queue::exceptionOccurred(function (JobExceptionOccurred $event) { + Bugsnag::leaveBreadcrumb('exceptionOccurred'); + }); } } diff --git a/features/queues.feature b/features/queues.feature index 53ed0413..1e360a82 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -26,10 +26,10 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 3 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon @@ -54,10 +54,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 3 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 3 breadcrumbs # attempt 2 When I discard the oldest error @@ -76,10 +76,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 3 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 3 breadcrumbs # attempt 3 When I discard the oldest error @@ -98,10 +98,10 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 3 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 3 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon @@ -123,9 +123,9 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 5.8 the event has 2 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 5.2 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker once @@ -149,11 +149,11 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 4 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once @@ -179,11 +179,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 4 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 4 breadcrumbs # attempt 2 When I discard the oldest error @@ -204,11 +204,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 4 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 4 breadcrumbs # attempt 3 When I discard the oldest error @@ -229,11 +229,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.8 the event has 4 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" + And on Laravel versions >= 5.2 the event has 4 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker once @@ -256,7 +256,7 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.8 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 5.8 the event has 3 breadcrumbs + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" + And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions >= 5.2 the event has 3 breadcrumbs From 78a948ff325363fc24389dad223ca151e58f8021 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 12:28:37 +0000 Subject: [PATCH 22/28] Test breadcrumbs in queues on Laravel 5.1 --- features/fixtures/docker-compose.yml | 1 + .../laravel51/app/Jobs/HandledJob.php | 2 + .../laravel51/app/Jobs/UnhandledJob.php | 3 ++ .../app/Providers/AppServiceProvider.php | 3 +- .../app/Providers/EventServiceProvider.php | 6 ++- features/queues.feature | 46 ++++++++++++------- 6 files changed, 43 insertions(+), 18 deletions(-) diff --git a/features/fixtures/docker-compose.yml b/features/fixtures/docker-compose.yml index c2b5cc3d..03a4acf9 100644 --- a/features/fixtures/docker-compose.yml +++ b/features/fixtures/docker-compose.yml @@ -15,6 +15,7 @@ services: - BUGSNAG_REGISTER_OOM_BOOTSTRAPPER - BUGSNAG_DISCARD_CLASSES - BUGSNAG_REDACTED_KEYS + - BUGSNAG_QUERY restart: "no" ports: - target: 8000 diff --git a/features/fixtures/laravel51/app/Jobs/HandledJob.php b/features/fixtures/laravel51/app/Jobs/HandledJob.php index b706f6d7..1e3c8ec4 100644 --- a/features/fixtures/laravel51/app/Jobs/HandledJob.php +++ b/features/fixtures/laravel51/app/Jobs/HandledJob.php @@ -17,6 +17,8 @@ class HandledJob extends Job implements SelfHandling, ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + Bugsnag::notifyException(new Exception('Handled :)')); } } diff --git a/features/fixtures/laravel51/app/Jobs/UnhandledJob.php b/features/fixtures/laravel51/app/Jobs/UnhandledJob.php index a836a768..33fc282d 100644 --- a/features/fixtures/laravel51/app/Jobs/UnhandledJob.php +++ b/features/fixtures/laravel51/app/Jobs/UnhandledJob.php @@ -6,6 +6,7 @@ use RuntimeException; use Illuminate\Contracts\Bus\SelfHandling; use Illuminate\Contracts\Queue\ShouldQueue; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class UnhandledJob extends Job implements SelfHandling, ShouldQueue { @@ -16,6 +17,8 @@ class UnhandledJob extends Job implements SelfHandling, ShouldQueue */ public function handle() { + Bugsnag::leaveBreadcrumb(__METHOD__); + throw new RuntimeException('uh oh :o'); } } diff --git a/features/fixtures/laravel51/app/Providers/AppServiceProvider.php b/features/fixtures/laravel51/app/Providers/AppServiceProvider.php index cf01e481..f69dc216 100644 --- a/features/fixtures/laravel51/app/Providers/AppServiceProvider.php +++ b/features/fixtures/laravel51/app/Providers/AppServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class AppServiceProvider extends ServiceProvider { @@ -13,7 +14,7 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { - // + Bugsnag::leaveBreadcrumb(__METHOD__); } /** diff --git a/features/fixtures/laravel51/app/Providers/EventServiceProvider.php b/features/fixtures/laravel51/app/Providers/EventServiceProvider.php index 58ce9624..3dfe0b82 100644 --- a/features/fixtures/laravel51/app/Providers/EventServiceProvider.php +++ b/features/fixtures/laravel51/app/Providers/EventServiceProvider.php @@ -4,6 +4,8 @@ use Illuminate\Contracts\Events\Dispatcher as DispatcherContract; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use Illuminate\Support\Facades\Queue; +use Bugsnag\BugsnagLaravel\Facades\Bugsnag; class EventServiceProvider extends ServiceProvider { @@ -28,6 +30,8 @@ public function boot(DispatcherContract $events) { parent::boot($events); - // + Queue::after(function () { + Bugsnag::leaveBreadcrumb('after'); + }); } } diff --git a/features/queues.feature b/features/queues.feature index 1e360a82..a1e4f983 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -26,10 +26,12 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 3 breadcrumbs + And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions < 5.2 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon @@ -55,9 +57,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 3 breadcrumbs + And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions < 5.2 the event has 2 breadcrumbs # attempt 2 When I discard the oldest error @@ -77,9 +81,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 3 breadcrumbs + And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions < 5.2 the event has 2 breadcrumbs # attempt 3 When I discard the oldest error @@ -99,9 +105,11 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 3 breadcrumbs + And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And on Laravel versions < 5.2 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon @@ -124,8 +132,9 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "unhandled" is false And the event "severityReason.type" equals "handledException" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 5.2 the event has 2 breadcrumbs + And the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker once @@ -149,11 +158,12 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 4 breadcrumbs + And on Laravel versions < 5.2 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once @@ -179,11 +189,12 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 4 breadcrumbs + And on Laravel versions < 5.2 the event has 2 breadcrumbs # attempt 2 When I discard the oldest error @@ -204,11 +215,12 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 4 breadcrumbs + And on Laravel versions < 5.2 the event has 2 breadcrumbs # attempt 3 When I discard the oldest error @@ -229,11 +241,12 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" And on Laravel versions >= 5.2 the event has 4 breadcrumbs + And on Laravel versions < 5.2 the event has 2 breadcrumbs @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker once @@ -256,7 +269,8 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" + And the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" And on Laravel versions >= 5.2 the event has 3 breadcrumbs + And on Laravel versions < 5.2 the event has 2 breadcrumbs From afbb2436ad2e471b77bec63162bc696724a933a9 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 12 Dec 2022 13:32:19 +0000 Subject: [PATCH 23/28] Simplify "on Laravel versions ..." step --- features/queues.feature | 302 +++++++++++++++++++------------- features/steps/laravel_steps.rb | 27 +++ 2 files changed, 208 insertions(+), 121 deletions(-) diff --git a/features/queues.feature b/features/queues.feature index a1e4f983..d0a15192 100644 --- a/features/queues.feature +++ b/features/queues.feature @@ -14,24 +14,30 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 3 breadcrumbs - And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 1 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 3 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + the event has 2 breadcrumbs + """ @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker as a daemon @@ -44,72 +50,90 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 3 breadcrumbs - And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 1 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 3 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + the event has 2 breadcrumbs + """ # attempt 2 When I discard the oldest error Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 2 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 3 breadcrumbs - And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 2 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 3 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + the event has 2 breadcrumbs + """ # attempt 3 When I discard the oldest error Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 3 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 3 breadcrumbs - And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 3 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 3 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + the event has 2 breadcrumbs + """ @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker as a daemon @@ -120,21 +144,27 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "Exception" And the exception "message" equals "Handled :)" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\HandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\HandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions < 5.2 the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" And the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 1 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\HandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\HandledJob" + the event has a "manual" breadcrumb named "before" + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" + """ @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queues when running the queue worker once @@ -146,24 +176,30 @@ Scenario: Unhandled exceptions are delivered from queues when running the queue Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 4 breadcrumbs - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 1 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 4 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has 2 breadcrumbs + """ @not-laravel-latest @not-lumen8 Scenario: Unhandled exceptions are delivered from queued jobs with multiple attmpts when running the queue worker once @@ -177,24 +213,30 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 4 breadcrumbs - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 1 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 4 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has 2 breadcrumbs + """ # attempt 2 When I discard the oldest error @@ -203,24 +245,30 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 2 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 4 breadcrumbs - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 2 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 4 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has 2 breadcrumbs + """ # attempt 3 When I discard the oldest error @@ -229,24 +277,30 @@ Scenario: Unhandled exceptions are delivered from queued jobs with multiple attm Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "RuntimeException" And the exception "message" equals "uh oh :o" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 3 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\UnhandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "error" And the event "unhandled" is true And the event "severityReason.type" equals "unhandledExceptionMiddleware" And the event "severityReason.attributes.framework" equals "Laravel" And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\UnhandledJob::handle" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "exceptionOccurred" - And on Laravel versions >= 5.2 the event has 4 breadcrumbs - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 3 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\UnhandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\UnhandledJob" + the event has a "manual" breadcrumb named "before" + the event has a "manual" breadcrumb named "exceptionOccurred" + the event has 4 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has 2 breadcrumbs + """ @not-laravel-latest @not-lumen8 Scenario: Handled exceptions are delivered from queues when running the queue worker once @@ -258,19 +312,25 @@ Scenario: Handled exceptions are delivered from queues when running the queue wo Then the error is valid for the error reporting API version "4.0" for the "Bugsnag Laravel" notifier And the exception "errorClass" equals "Exception" And the exception "message" equals "Handled :)" - And on Laravel versions >= 5.2 the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" - And on Laravel versions >= 5.2 the event "metaData.job.queue" equals "default" - And on Laravel versions >= 5.2 the event "metaData.job.attempts" equals 1 - And on Laravel versions >= 5.2 the event "metaData.job.connection" equals "database" - And on Laravel versions >= 5.2 the event "metaData.job.resolved" equals "App\Jobs\HandledJob" - And on Laravel versions >= 5.2 the event "app.type" equals "Queue" - And on Laravel versions >= 5.2 the event "context" equals "App\Jobs\HandledJob" - And on Laravel versions < 5.2 the event "metaData.job" is null And the event "severity" equals "warning" And the event "unhandled" is false And the event "severityReason.type" equals "handledException" And the event has a "manual" breadcrumb named "App\Providers\AppServiceProvider::boot" - And on Laravel versions >= 5.2 the event has a "manual" breadcrumb named "before" And the event has a "manual" breadcrumb named "App\Jobs\HandledJob::handle" - And on Laravel versions >= 5.2 the event has 3 breadcrumbs - And on Laravel versions < 5.2 the event has 2 breadcrumbs + And on Laravel versions >= 5.2: + """ + the event "metaData.job.name" equals "Illuminate\Queue\CallQueuedHandler@call" + the event "metaData.job.queue" equals "default" + the event "metaData.job.attempts" equals 1 + the event "metaData.job.connection" equals "database" + the event "metaData.job.resolved" equals "App\Jobs\HandledJob" + the event "app.type" equals "Queue" + the event "context" equals "App\Jobs\HandledJob" + the event has a "manual" breadcrumb named "before" + the event has 3 breadcrumbs + """ + And on Laravel versions < 5.2: + """ + the event "metaData.job" is null + the event has 2 breadcrumbs + """ diff --git a/features/steps/laravel_steps.rb b/features/steps/laravel_steps.rb index 23823baf..f7bddfc6 100644 --- a/features/steps/laravel_steps.rb +++ b/features/steps/laravel_steps.rb @@ -155,3 +155,30 @@ def cp(service, source:, destination:) $logger.info("Skipping step on Laravel v#{Laravel.version}: #{step_to_run}") end end + +# conditionally run a number of steps if the laravel version matches a specified version +# +# e.g. this will only run the indented steps on Laravel 5.2 and above: +# on Laravel versions > 5.1: +# """ +# the event "app.type" equals "Queue" +# the event "other.thing" equals "yes" +# """ +Then(/^on Laravel versions (>=?|<=?|==) ([0-9.]+):/) do |operator, version, steps_to_run| + should_run_steps = Laravel.version.send(operator, version) + + # make sure this step is debuggable! + $logger.debug("Laravel v#{Laravel.version} #{operator} #{version}? #{should_run_steps}") + + if should_run_steps + steps_to_run.each_line(chomp: true) do |step_to_run| + step(step_to_run) + end + else + indent = " " * 4 + # e.g. "a step\nanother step\n" -> " 1) a step\n 2) another step" + steps_indented = steps_to_run.each_line.map.with_index(1) { |step, i| "#{indent}#{i}) #{step.chomp}" }.join("\n") + + $logger.info("Skipping steps on Laravel v#{Laravel.version}:\n#{steps_indented}") + end +end From 749e8ef8da69b0df0bb68073fbb1e2ef26cde4c2 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 3 Jan 2023 09:43:22 +0000 Subject: [PATCH 24/28] Ensure events are sent from queues run by Vapor Currently we never flush the queue of events when using Laravel Vapor because it does not call our shutdown function or the 'looping' event We need to: 1. flush events in 'after' and 'exceptionOccurred' in order to send any events created during the execution of a job 2. disable batch sending in 'after' and 'exceptionOccurred' so that any events created when a job finishes get sent synchronously. Otherwise we'd fail to send these events if the queue worker doesn't run another job 3. Re-enable batch sending in 'before' if we previously disabled it. This allows users to get the performance benefits of batch sending while their job is running (though it's much less relevant in a queue process) --- src/BugsnagServiceProvider.php | 62 ++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/BugsnagServiceProvider.php b/src/BugsnagServiceProvider.php index 9fba2014..627f8a6a 100644 --- a/src/BugsnagServiceProvider.php +++ b/src/BugsnagServiceProvider.php @@ -180,6 +180,68 @@ protected function setupQueue(QueueManager $queue) $this->app->make(Tracker::class)->set($job); }); + + $this->setupQueueForLaravelVapor($queue); + } + + /** + * Setup queue events for Laravel Vapor. + * + * This is required because Laravel Vapor's queue system doesn't behave as + * a daemonised queue worker (the 'looping' event never fires) but also + * doesn't behave as a non-daemonised queue worker (our shutdown function + * never fires). + * + * @param QueueManager $queue + * + * @return void + */ + private function setupQueueForLaravelVapor(QueueManager $queue) + { + // ensure we're running on vapor + // this is how vapor-core does it, e.g.: + // https://github.com/laravel/vapor-core/blob/61437221090850ba6e51dce15d0058d362654f9b/src/ConfiguresAssets.php#L16-L19 + if (!isset($_ENV['VAPOR_SSM_PATH'])) { + return; + } + + // used to keep track of if we're the ones disabling batch sending, so we + // know if we need to re-enable it - if the user disables batch sending + // then they don't want it enabled at all + static $batchSendingWasDisabledByUs = false; + + $queue->before(function () use (&$batchSendingWasDisabledByUs) { + // only re-enable batch sending if we're the ones disabling it + // this allows users to disable batch sending entirely + if ($batchSendingWasDisabledByUs) { + $this->app->bugsnag->setBatchSending(true); + } + }); + + $flush = function () use (&$batchSendingWasDisabledByUs) { + // flush any events created in this job + $this->app->bugsnag->flush(); + + // disable batch sending so any events after this get sent synchronously + // this is important as exceptions are logged after the 'exceptionOccurred' + // event fires, so the above flush is too early to send them + // these exceptions would get sent after processing the next queued job, + // but we'd still drop the last event when this queue worker stops running + if ($this->app->bugsnag->isBatchSending()) { + $this->app->bugsnag->setBatchSending(false); + $batchSendingWasDisabledByUs = true; + } + }; + + // added in 5.2.41 + if (method_exists($queue, 'after')) { + $queue->after($flush); + } + + // added in 5.2.41 + if (method_exists($queue, 'exceptionOccurred')) { + $queue->exceptionOccurred($flush); + } } /** From a4cf3c923c05848d97356e4096c52f032a62d736 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 3 Jan 2023 09:44:24 +0000 Subject: [PATCH 25/28] Clear breadcrumbs in 'before' on Laravel Vapor This stops breadcrumbs leaking between jobs --- src/BugsnagServiceProvider.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/BugsnagServiceProvider.php b/src/BugsnagServiceProvider.php index 627f8a6a..e12bc9c6 100644 --- a/src/BugsnagServiceProvider.php +++ b/src/BugsnagServiceProvider.php @@ -211,6 +211,9 @@ private function setupQueueForLaravelVapor(QueueManager $queue) static $batchSendingWasDisabledByUs = false; $queue->before(function () use (&$batchSendingWasDisabledByUs) { + // clear breadcrumbs to stop them leaking between jobs + $this->app->bugsnag->clearBreadcrumbs(); + // only re-enable batch sending if we're the ones disabling it // this allows users to disable batch sending entirely if ($batchSendingWasDisabledByUs) { From 7ab021bb54cfedc7907e457a823da061d66fb46f Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Tue, 3 Jan 2023 10:21:41 +0000 Subject: [PATCH 26/28] Update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd32bd63..87f0bcd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,19 @@ Changelog ## TBD +### Enhancements + +* Ensure events are sent from queues when using Laravel Vapor + [#511](https://github.com/bugsnag/bugsnag-laravel/pull/511) + ### Bug fixes * Fix events from CLI commands always being handled when using the `NunoMaduro\Collision` package [#503](https://github.com/bugsnag/bugsnag-laravel/pull/503) +* Fix breadcrumbs leaking between queued jobs when using Laravel Vapor + [#511](https://github.com/bugsnag/bugsnag-laravel/pull/511) + ## 2.25.0 (2022-10-25) ### Enhancements From 0c7c879caeff43685bbf1411735c6cda755655af Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 16 Jan 2023 10:32:15 +0000 Subject: [PATCH 27/28] Bump version --- src/BugsnagServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BugsnagServiceProvider.php b/src/BugsnagServiceProvider.php index e12bc9c6..146fc37d 100644 --- a/src/BugsnagServiceProvider.php +++ b/src/BugsnagServiceProvider.php @@ -37,7 +37,7 @@ class BugsnagServiceProvider extends ServiceProvider * * @var string */ - const VERSION = '2.25.0'; + const VERSION = '2.25.1'; /** * Boot the service provider. From 9133be2bec167eb61c96167ed4abd894f896ddc0 Mon Sep 17 00:00:00 2001 From: Joe Haines Date: Mon, 16 Jan 2023 10:32:22 +0000 Subject: [PATCH 28/28] Add version & date to changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87f0bcd8..809122ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Changelog ========= -## TBD +## v2.25.1 (2023-01-17) ### Enhancements