Skip to content

Latest commit

Β 

History

History
439 lines (309 loc) Β· 12.8 KB

File metadata and controls

439 lines (309 loc) Β· 12.8 KB

Laravel Exception Notifier

Latest Version on Packagist Total Downloads License

Version 2.0 - Major upgrade with Laravel 12+ support! πŸš€

Laravel Exception Notifier is a production-ready exception notification system for Laravel 12+ applications. Get instant email alerts when exceptions occur in your application with intelligent rate limiting, customizable templates, and comprehensive context data.

πŸ†• What's New in v2.0

  • ✨ Laravel 12+ Support - Modern bootstrap/app.php pattern
  • ✨ PHP 8.2+ Required - Latest PHP features and performance
  • ✨ Per-Signature Rate Limiting - Each exception tracked separately
  • ✨ Critical Exception Bypass - Important errors always notify
  • ✨ Enhanced Bot Detection - Better false positive filtering
  • ✨ Zero-Loop Guarantee - Fixed infinite loop bug with dependency injection
  • ✨ Email Branding - Customizable logo, colors, and footer

Upgrading from v1.x? See UPGRADE.md for migration guide.

✨ Features

  • 🚨 Instant Email Notifications - Get notified immediately when exceptions occur
  • 🎯 Smart Rate Limiting - Per-exception-signature rate limiting to prevent email spam
  • πŸ”₯ Critical Exception Bypass - Critical exceptions always bypass rate limits
  • πŸ“Š Rich Context Data - Stack traces, request details, user information, and more
  • 🎨 Customizable Email Templates - Beautiful, responsive HTML email templates
  • πŸ€– Bot Detection - Automatically ignore exceptions from bots and crawlers
  • πŸ”§ Artisan Commands - Manage rate limits and test notifications via CLI
  • 🌍 Environment-Aware - Silent mode in local environment during development
  • πŸ“ Detailed Logging - All exceptions still logged even when email suppressed
  • ⚑ Zero Performance Impact - Notifications wrapped in try-catch to never break your app

πŸ“‹ Requirements

  • PHP 8.2 or higher
  • Laravel 12.0 or higher
  • Mail configuration (SMTP, Mailgun, SES, etc.)

πŸ“¦ Installation

Install the package via Composer:

composer require damku999/exception-notifier

Publish Configuration

Publish the configuration file:

php artisan vendor:publish --tag="exception-notifier-config"

This will create config/exception_notifier.php with all available options.

Publish Email Templates (Optional)

If you want to customize the email templates:

php artisan vendor:publish --tag="exception-notifier-views"

Templates will be published to resources/views/vendor/exception-notifier/.

Publish Migrations (Optional)

If you want to use database-backed rate limiting:

php artisan vendor:publish --tag="exception-notifier-migrations"
php artisan migrate

βš™οΈ Configuration

Environment Variables

Add these to your .env file:

# Enable exception email notifications (default: false)
EXCEPTION_EMAIL_ENABLED=true

# Silent mode in local environment (default: true)
EXCEPTION_EMAIL_SILENT_LOCAL=true

# Email recipients (comma-separated)
EXCEPTION_EMAIL_TO=admin@example.com,dev@example.com

# Rate limiting (default: 10 emails per hour per signature)
EXCEPTION_EMAIL_MAX_PER_HOUR=10
EXCEPTION_EMAIL_RATE_WINDOW=3600

Basic Setup

Update your bootstrap/app.php to use the exception notifier:

<?php

use Damku999\ExceptionNotifier\JsonExceptionHandler;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->render(function (Throwable $e) {
            return app(JsonExceptionHandler::class)->handle($e);
        });
    })->create();

Advanced Configuration

Edit config/exception_notifier.php for advanced options:

return [
    // Enable/disable globally
    'enabled' => env('EXCEPTION_EMAIL_ENABLED', false),

    // Silent mode in local environment
    'silent_in_local' => env('EXCEPTION_EMAIL_SILENT_LOCAL', true),

    // Email recipients
    'recipients' => array_filter(array_map('trim', explode(',', env('EXCEPTION_EMAIL_TO', '')))),

    // Fallback recipients if none specified
    'fallback_recipients' => ['admin@example.com'],

    // Rate limiting
    'max_emails_per_signature_per_hour' => env('EXCEPTION_EMAIL_MAX_PER_HOUR', 10),
    'rate_limit_window' => env('EXCEPTION_EMAIL_RATE_WINDOW', 3600),

    // Ignored exceptions (won't send emails)
    'ignored_exceptions' => [
        \Illuminate\Validation\ValidationException::class,
        \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class,
        \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException::class,
        \Illuminate\Auth\AuthenticationException::class,
    ],

    // Critical exceptions (bypass rate limits)
    'critical_exceptions' => [
        \Illuminate\Database\QueryException::class,
    ],

    // Bot user agents to ignore
    'ignored_bots' => [
        'googlebot', 'bingbot', 'crawler', 'spider', 'bot',
    ],

    // Include context data in emails
    'include_request_data' => true,
    'include_user_data' => true,
    'include_stack_trace' => true,
    'max_stack_trace_depth' => 10,

    // Send suppression notice when rate limit reached
    'send_suppression_notice' => true,
];

πŸš€ Usage

Automatic Exception Handling

Once configured in bootstrap/app.php, the package automatically catches and notifies you of exceptions:

// Any uncaught exception will trigger an email notification
throw new \Exception('Something went wrong!');

// Validation exceptions are ignored by default (configurable)
throw ValidationException::withMessages(['email' => 'Invalid email']);

// Database exceptions are marked as critical (always sent)
DB::table('non_existent')->get(); // Triggers critical email

Manual Exception Notification

You can manually trigger exception notifications:

use Damku999\ExceptionNotifier\Facades\ExceptionNotifier;

try {
    // Your code
} catch (\Throwable $e) {
    ExceptionNotifier::notify($e);

    // Continue with your error handling
}

Checking Rate Limits

use Damku999\ExceptionNotifier\Facades\ExceptionNotifier;

// Check if rate limit exceeded for specific exception
$signature = ExceptionNotifier::generateSignature($exception);
$exceeded = ExceptionNotifier::isRateLimitExceeded($signature);

// Get current count for signature
$count = ExceptionNotifier::getRateLimitCount($signature);

// Get all rate limit statuses
$statuses = ExceptionNotifier::getRateLimitStatus();

πŸ”§ Artisan Commands

View Rate Limit Status

View current rate limit status for all exception signatures:

php artisan exception:rate-limit-status

Output:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Exception Signature                                          β”‚ Count β”‚ Max β”‚ TTL (s)  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Exception:app/Http/Controllers/UserController.php:45         β”‚ 8     β”‚ 10  β”‚ 2847     β”‚
β”‚ QueryException:app/Models/User.php:123                       β”‚ 15    β”‚ 10  β”‚ 1523     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Clear Rate Limits

Clear all rate limits:

php artisan exception:clear-rate-limits

Clear specific signature:

php artisan exception:clear-rate-limits --signature="Exception:app/Http/Controllers/UserController.php:45"

Test Exception Emails

Send a test exception email:

php artisan exception:test

Send test with custom exception type:

php artisan exception:test --type=critical

πŸ“§ Email Templates

The package includes two beautiful, responsive email templates:

Exception Notification Email

Sent when an exception occurs (within rate limits):

  • Exception Summary - Class, message, file, line, signature
  • Stack Trace - Formatted call stack with file/line numbers
  • Request Details - URL, method, IP, user agent
  • User Context - Authenticated user information
  • Environment Info - Environment name and timestamp
  • Rate Limit Status - Current count vs maximum allowed

Rate Limit Suppression Email

Sent once when rate limit is reached:

  • Rate Limit Info - Signature, max count, time remaining
  • What This Means - Explanation of suppression
  • Action Required - Steps to investigate and resolve
  • Helpful Commands - CLI commands to manage rate limits

Customizing Templates

Publish the views and edit them:

php artisan vendor:publish --tag="exception-notifier-views"

Templates location: resources/views/vendor/exception-notifier/

Customizing Email Branding

Override the branding configuration:

// In your AppServiceProvider or config
config([
    'exception_notifier.branding' => [
        'email_logo' => 'images/logo.png',
        'primary_color' => '#007bff',
        'text_color' => '#333333',
        'footer_text' => 'Your Company Name',
        'support_email' => 'support@example.com',
    ],
]);

πŸ§ͺ Testing

Run the test suite:

composer test

Run tests with coverage:

composer test:coverage

πŸ“Š Exception Signature Format

The package generates unique signatures for each exception using:

Format: ExceptionClass:FilePath:LineNumber
Example: Exception:app/Http/Controllers/UserController.php:45

This ensures:

  • βœ… Same exception at same location = same signature
  • βœ… Rate limiting works per unique error
  • βœ… Different locations = different signatures

πŸ”’ Security

Preventing Infinite Loops

The package is designed to never break your application:

// In JsonExceptionHandler
try {
    $this->notifierService->notify($e);
} catch (Throwable $notificationError) {
    // Silently fail if notification fails
    Log::error('Exception notification failed', [
        'error' => $notificationError->getMessage(),
    ]);
}

Bot Protection

Automatically ignores exceptions from bots to prevent spam:

'ignored_bots' => [
    'googlebot', 'bingbot', 'slurp', 'crawler', 'spider',
    'bot', 'facebookexternalhit', 'twitterbot', 'whatsapp',
    'telegram', 'curl', 'wget',
],

🀝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

Development Setup

# Clone the repository
git clone https://github.com/damku999/exception-notifier.git
cd exception-notifier

# Install dependencies
composer install

# Run tests
composer test

# Run code style checks
composer lint

πŸ“ Changelog

Please see CHANGELOG.md for recent changes.

πŸ“„ License

The MIT License (MIT). Please see LICENSE.md for more information.

πŸ™ Credits

  • Author: Darshan Baraiya
  • GitHub: @damku999
  • Built with: Laravel 12, PHP 8.2

πŸ’‘ Use Cases

Perfect for:

  • 🏒 Production Applications - Monitor critical production errors
  • πŸ”§ Staging Environments - Catch bugs before production
  • πŸ“Š API Services - Track API failures and exceptions
  • πŸš€ Microservices - Centralized exception monitoring
  • πŸ‘₯ Team Collaboration - Multiple developers receive alerts

πŸ†˜ Support


Developed by Darshan Baraiya