Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Failed Job Monitor Laravel Package

spatie/laravel-failed-job-monitor

Send instant notifications when Laravel queued jobs fail. Uses Laravel’s notification system with built-in Mail and Slack support, configurable via env/config, and easy install/publish. Great for monitoring production queues and alerting the right people.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require spatie/laravel-failed-job-monitor
    

    For Slack support:

    composer require guzzlehttp/guzzle
    
  2. Publish the config:

    php artisan vendor:publish --tag=failed-job-monitor-config
    
  3. Configure .env:

    FAILED_JOB_MONITOR_ENABLED=true
    FAILED_JOB_CHANNELS=mail,slack
    FAILED_JOB_EMAILS=admin@example.com
    FAILED_JOB_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
    
  4. Verify Horizon is configured (if using Laravel Horizon): Ensure horizon.path is set in your config/horizon.php (default: horizon).

First Use Case

Trigger a failing job to test notifications:

use App\Jobs\FailingJob;

dispatch(new FailingJob());

Check your email/Slack for the notification.


Implementation Patterns

Core Workflow

  1. Job Failure Handling: The package automatically hooks into Laravel's job failure system. When a job fails, it triggers the notification pipeline.

  2. Notification Channels:

    • Mail: Uses Laravel's mail system with a default template.
    • Slack: Requires a webhook URL and sends formatted messages.
    • Custom Channels: Extend the Notification class to add new channels (e.g., Discord, Teams).
  3. Dynamic Filtering: Use notificationFilter to conditionally suppress notifications:

    // config/failed-job-monitor.php
    'notificationFilter' => [App\Filters\FailedJobFilter::class, 'shouldNotify'],
    

    Example filter:

    public static function shouldNotify(Notification $notification): bool {
        return !app()->environment('local'); // Skip in local
    }
    
  4. Custom Notifications: Override the default notification class:

    // config/failed-job-monitor.php
    'notification' => App\Notifications\CustomFailedJobNotification::class,
    

    Example custom notification:

    use Spatie\FailedJobMonitor\Notification as BaseNotification;
    
    class CustomFailedJobNotification extends BaseNotification {
        public function toMail($notifiable) {
            return (new MailMessage)
                ->subject('Custom Job Failure Alert')
                ->line('Job failed: ' . $this->failedJob->job);
        }
    }
    
  5. Notifiable Customization: Replace the default Notifiable class to use custom logic (e.g., dynamic recipients):

    // config/failed-job-monitor.php
    'notifiable' => App\Notifiables\DynamicRecipientNotifiable::class,
    

Integration Tips

  • Horizon Compatibility: The package includes a link to Horizon in emails (if configured). Ensure horizon.path is set in config/horizon.php.

    // config/horizon.php
    'path' => env('HORIZON_PATH', 'horizon'),
    
  • Environment-Specific Config: Disable notifications in local environments:

    FAILED_JOB_MONITOR_ENABLED=${APP_ENV !== 'local'}
    
  • Batch Processing: For high-volume queues, consider throttling notifications to avoid alert fatigue:

    // In your filter
    public static function shouldNotify(Notification $notification): bool {
        return cache()->forget("last_failed_job_alert_{$notification->failedJob->id}");
    }
    

Gotchas and Tips

Pitfalls

  1. Configuration Serialization: Avoid closures in notificationFilter—use static methods in classes instead to prevent config:cache errors.

  2. Slack Webhook Validation: Ensure the Slack webhook URL is correct and accessible from your queue worker’s environment (e.g., Docker, serverless).

  3. Horizon Path Mismatch: If Horizon is configured with a custom path (e.g., /admin/horizon), update horizon.path in config/horizon.php to avoid broken links in emails.

  4. Queue Worker Isolation: Queue workers must have access to the same environment variables (e.g., .env) as your application. Use queue:work with --env=production to match your deployment.

  5. Failed Job Retries: If jobs are retried, notifications will fire on each failure. Use notificationFilter to deduplicate:

    public static function shouldNotify(Notification $notification): bool {
        return !cache()->has("failed_job_{$notification->failedJob->id}");
    }
    

Debugging

  • No Notifications?: Check:

    • FAILED_JOB_MONITOR_ENABLED is true.
    • The queue worker is processing jobs (tail logs with queue:work --once).
    • The failed_jobs table exists (run php artisan queue:failed-table if missing).
  • Slack Notifications Failing: Verify the webhook URL and test with:

    curl -X POST -H 'Content-type: application/json' --data '{"text":"Test"}' YOUR_WEBHOOK_URL
    
  • Custom Notifications Not Triggering: Ensure your custom class extends Spatie\FailedJobMonitor\Notification and is properly registered in the config.

Tips

  1. Rich Email Content: Customize the email template by publishing views:

    php artisan vendor:publish --tag=failed-job-monitor-views
    

    Edit resources/views/vendor/failed-job-monitor/email.blade.php.

  2. Slack Formatting: Use Slack’s block kit for rich messages:

    public function toSlack($notifiable, array $data) {
        return [
            'blocks' => [
                [
                    'type' => 'section',
                    'text' => [
                        'type' => 'mrkdwn',
                        'text' => '*Job Failed* :rotating_light:'
                    ]
                ],
                // Add more blocks...
            ]
        ];
    }
    
  3. Rate Limiting: Add rate limiting to avoid notification spam:

    public static function shouldNotify(Notification $notification): bool {
        return now()->diffInMinutes(cache()->get("last_alert")) > 5;
    }
    
  4. Dynamic Recipients: Use the Notifiable class to fetch recipients dynamically (e.g., from a database):

    class DynamicRecipientNotifiable implements ShouldQueue {
        public function routeNotificationForMail() {
            return User::where('role', 'admin')->pluck('email');
        }
    }
    
  5. Testing: Use Laravel’s fake() for notifications in tests:

    $this->fake();
    $this->assertNothingSent();
    
    // Trigger a failing job
    $this->assertSent(FailedJobNotification::class);
    
  6. Performance: For large-scale systems, batch failed job processing to reduce database load:

    // In your filter
    public static function shouldNotify(Notification $notification): bool {
        return now()->startOfHour()->lt($notification->failedJob->failed_at);
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony