├── resources └── views │ ├── .gitkeep │ └── livewire │ └── 404-monitor.blade.php ├── 404-monitor.png ├── CHANGELOG.md ├── src ├── NotFoundMonitorServiceProvider.php ├── Livewire │ └── NotFoundMonitor.php └── Recorders │ └── NotFoundRecorder.php ├── LICENSE.md ├── composer.json └── README.md /resources/views/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /404-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geowrgetudor/404-monitor/HEAD/404-monitor.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `404-monitor` will be documented in this file. 4 | 5 | ## v2.0 - 2025-06-16 6 | 7 | Support for Laravel 11 & 12. 8 | 9 | Dropped support for Laravel 10. (use v1.4 if you still need that) 10 | 11 | ## v1.4 - 2024-03-14 12 | 13 | - Add support for PHP 8.2, 8.3 14 | - Add support for Laravel 11 15 | 16 | ## v1.1 - 2023-12-06 17 | 18 | Fix config & view publishing 19 | 20 | ## v1.0 - 2023-12-06 21 | 22 | Track 404 pages inside Laravel Pulse 23 | -------------------------------------------------------------------------------- /src/NotFoundMonitorServiceProvider.php: -------------------------------------------------------------------------------- 1 | name('404-monitor') 17 | ->hasViews(); 18 | } 19 | 20 | public function boot(): void 21 | { 22 | parent::boot(); 23 | 24 | $this->loadViewsFrom(__DIR__ . '/../resources/views', '404-monitor'); 25 | 26 | $this->callAfterResolving('livewire', function (LivewireManager $livewire, Application $app) { 27 | $livewire->component('404-monitor', NotFoundMonitor::class); 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) George Tudor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Livewire/NotFoundMonitor.php: -------------------------------------------------------------------------------- 1 | remember( 22 | fn () => Pulse::aggregate( 23 | 'page_not_found', 24 | 'count', 25 | $this->periodAsInterval(), 26 | 'count', 27 | )->map(function ($row) { 28 | [$method, $uri] = json_decode($row->key, flags: JSON_THROW_ON_ERROR); 29 | 30 | return (object) [ 31 | 'uri' => $uri, 32 | 'method' => $method, 33 | 'count' => $row->count, 34 | ]; 35 | }), 36 | ); 37 | 38 | return View::make('404-monitor::livewire.404-monitor', [ 39 | 'notFoundPages' => $notFoundPages, 40 | ]); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Recorders/NotFoundRecorder.php: -------------------------------------------------------------------------------- 1 | afterResolving( 32 | $app, 33 | Kernel::class, 34 | fn (Kernel $kernel) => $kernel->whenRequestLifecycleIsLongerThan(-1, $record) // @phpstan-ignore method.notFound 35 | ); 36 | } 37 | 38 | public function record(Carbon $startedAt, Request $request, Response $response): void 39 | { 40 | if ($response->getStatusCode() !== 404) { 41 | return; 42 | } 43 | 44 | if ($this->shouldIgnore($request->fullUrl())) { 45 | return; 46 | } 47 | 48 | $this->pulse->record( 49 | type: 'page_not_found', 50 | key: json_encode([$request->method(), $request->fullUrl()], flags: JSON_THROW_ON_ERROR), 51 | timestamp: $startedAt, 52 | )->count(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /resources/views/livewire/404-monitor.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | @if ($notFoundPages->isEmpty()) 10 | 11 | @else 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{ __('Page') }} 21 | {{ __('Method') }} 22 | {{ __('Count') }} 23 | 24 | 25 | 26 | @foreach ($notFoundPages as $key => $page) 27 | 28 | 29 | 30 | 32 | {{ $page->uri }} 33 | 34 | 35 | 36 | 37 | 38 | 39 | {{ (int) $page->count }} 40 | 41 | 42 | @endforeach 43 | 44 | 45 | @endif 46 | 47 | 48 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geowrgetudor/404-monitor", 3 | "description": "Monitor 404 pages within Laravel Pulse", 4 | "keywords": [ 5 | "laravel", 6 | "pulse", 7 | "404-monitor" 8 | ], 9 | "homepage": "https://github.com/geowrgetudor/404-monitor", 10 | "license": "MIT", 11 | "authors": [ 12 | { 13 | "name": "George Tudor", 14 | "email": "georgebitq@gmail.com", 15 | "role": "Developer" 16 | } 17 | ], 18 | "require": { 19 | "php": "^8.2|^8.3|^8.4", 20 | "spatie/laravel-package-tools": "^1.14.0", 21 | "illuminate/contracts": "^11.0|^12.0", 22 | "laravel/pulse": "^1.3.1" 23 | }, 24 | "require-dev": { 25 | "laravel/pint": "^1.0", 26 | "nunomaduro/collision": "^7.8|^8.0", 27 | "orchestra/testbench": "^9.0|^10.0", 28 | "pestphp/pest": "^2.20", 29 | "pestphp/pest-plugin-arch": "^2.0", 30 | "pestphp/pest-plugin-laravel": "^2.0" 31 | }, 32 | "autoload": { 33 | "psr-4": { 34 | "Geow\\NotFoundMonitor\\": "src/" 35 | } 36 | }, 37 | "autoload-dev": { 38 | "psr-4": { 39 | "Geow\\NotFoundMonitor\\Tests\\": "tests/", 40 | "Workbench\\App\\": "workbench/app/" 41 | } 42 | }, 43 | "scripts": { 44 | "post-autoload-dump": "@composer run prepare", 45 | "clear": "@php vendor/bin/testbench package:purge-404-monitor --ansi", 46 | "prepare": "@php vendor/bin/testbench package:discover --ansi", 47 | "build": [ 48 | "@composer run prepare", 49 | "@php vendor/bin/testbench workbench:build --ansi" 50 | ], 51 | "start": [ 52 | "Composer\\Config::disableProcessTimeout", 53 | "@composer run build", 54 | "@php vendor/bin/testbench serve" 55 | ], 56 | "analyse": "vendor/bin/phpstan analyse", 57 | "test": "vendor/bin/pest", 58 | "test-coverage": "vendor/bin/pest --coverage", 59 | "format": "vendor/bin/pint" 60 | }, 61 | "config": { 62 | "sort-packages": true, 63 | "allow-plugins": { 64 | "pestphp/pest-plugin": true, 65 | "phpstan/extension-installer": true 66 | } 67 | }, 68 | "extra": { 69 | "laravel": { 70 | "providers": [ 71 | "Geow\\NotFoundMonitor\\NotFoundMonitorServiceProvider" 72 | ] 73 | } 74 | }, 75 | "minimum-stability": "stable", 76 | "prefer-stable": true 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

404 Monitor for Laravel Pulse

2 | 3 | # Track 404 errors in Laravel Pulse 4 | 5 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/geowrgetudor/404-monitor.svg?style=flat-square)](https://packagist.org/packages/geowrgetudor/404-monitor) 6 | [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/geowrgetudor/404-monitor/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/geowrgetudor/404-monitor/actions?query=workflow%3Arun-tests+branch%3Amain) 7 | [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/geowrgetudor/404-monitor/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/geowrgetudor/404-monitor/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain) 8 | [![Total Downloads](https://img.shields.io/packagist/dt/geowrgetudor/404-monitor.svg?style=flat-square)](https://packagist.org/packages/geowrgetudor/404-monitor) 9 | 10 | This is a Laravel Pulse package that allows you to track 404 errors. 11 | 12 | ## Installation 13 | 14 | You can install the package via composer: 15 | 16 | ```bash 17 | composer require geowrgetudor/404-monitor 18 | ``` 19 | 20 | Optionally, you can publish the views using 21 | 22 | ```bash 23 | php artisan vendor:publish --tag="404-monitor-views" 24 | ``` 25 | 26 | ## Usage 27 | 28 | Register the recorder in `config/pulse.php`. (If you don\'t have this file make sure you have published the config file of Laravel Pulse using `php artisan vendor:publish --tag=pulse-config`) 29 | 30 | ``` 31 | return [ 32 | // ... 33 | 34 | 'recorders' => [ 35 | // Existing recorders... 36 | 37 | \Geow\NotFoundMonitor\Recorders\NotFoundRecorder::class => [ 38 | 'enabled' => true, 39 | 'ignore' => [ 40 | // Ignore specific urls (regex supported) 41 | ], 42 | ] 43 | ] 44 | ] 45 | ``` 46 | 47 | Publish Laravel Pulse `dashboard.blade.php` view using `php artisan vendor:publish --tag=pulse-dashboard` 48 | 49 | Then you can modify the file and add the 404-monitor livewire template. 50 | 51 | ```php 52 | 53 | ``` 54 | 55 | ## Testing 56 | 57 | ```bash 58 | composer test 59 | ``` 60 | 61 | ## Changelog 62 | 63 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 64 | 65 | ## Contributing 66 | 67 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details. 68 | 69 | ## Security Vulnerabilities 70 | 71 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 72 | 73 | ## Credits 74 | 75 | - [George Tudor](https://github.com/geowrgetudor) 76 | - [All Contributors](../../contributors) 77 | 78 | ## License 79 | 80 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 81 | --------------------------------------------------------------------------------