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 Schedule Monitor Laravel Package

spatie/laravel-schedule-monitor

Monitor Laravel scheduled tasks by logging each run’s start, finish, failure, or skip to the database. Use an Artisan list command to see execution history and spot issues. Optional Oh Dear sync alerts you when tasks fail or don’t run on time.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-schedule-monitor
    php artisan vendor:publish --provider="Spatie\ScheduleMonitor\ScheduleMonitorServiceProvider" --tag="schedule-monitor-migrations"
    php artisan migrate
    
  2. First Sync:

    php artisan schedule-monitor:sync
    
  3. Verify Sync:

    php artisan schedule-monitor:list
    

First Use Case: Debugging a Missed Job

  • Run schedule-monitor:list to check if a job is marked as "late" (red background).
  • Use schedule-monitor:list --failed to see jobs that failed.
  • Check the monitored_scheduled_task_log_items table for execution details (memory, runtime, output).

Implementation Patterns

Core Workflow

  1. Schedule Definition:

    // app/Console/Kernel.php
    $schedule->command('backup:run')->dailyAt('2:00')->monitorName('daily-backup');
    $schedule->job(new SendReportJob())->hourly()->graceTimeInMinutes(10);
    
  2. Post-Deployment Sync: Add to your deployment script:

    php artisan schedule-monitor:sync --keep-old  # Non-destructive sync for Oh Dear
    
  3. Monitoring:

    • CLI:
      php artisan schedule-monitor:list --failed  # Filter failures
      php artisan schedule-monitor:list --since=2024-01-01  # Time range
      
    • Database: Query monitored_scheduled_task_log_items for custom reports:
      $logs = MonitoredScheduledTaskLogItem::where('task_name', 'daily-backup')
          ->where('status', 'failed')
          ->orderBy('created_at', 'desc')
          ->get();
      

Integration Tips

  • Oh Dear Sync: Configure .env with OH_DEAR_API_TOKEN and OH_DEAR_MONITOR_ID, then run:

    php artisan schedule-monitor:sync
    

    Verify with:

    php artisan schedule-monitor:verify
    
  • Output Storage: Enable for commands/jobs:

    $schedule->command('backup:run')->storeOutputInDb();
    

    Retrieve output via:

    $logItem->meta->output;  // JSON-decoded output
    
  • Grace Time: Override globally in config/schedule-monitor.php or per-task:

    $schedule->command('long-running-job')->graceTimeInMinutes(30);
    
  • Pruning Logs: Add to app/Console/Kernel.php:

    $schedule->command('model:prune', [
        '--model' => \Spatie\ScheduleMonitor\Models\MonitoredScheduledTaskLogItem::class
    ])->daily();
    

Gotchas and Tips

Pitfalls

  1. Name Collisions:

    • Changing a task’s name (e.g., monitorName()) deletes old logs for that task.
    • Fix: Use consistent naming conventions or avoid renaming.
  2. Oh Dear Sync Issues:

    • Timeouts: Ensure OH_DEAR_QUEUE is a dedicated queue with workers.
    • False Positives: Set realistic graceTimeInMinutes (e.g., 10–30 mins for long jobs).
    • Debug: Enable OH_DEAR_DEBUG_LOGGING=true for connection issues.
  3. Multitenancy:

    • Forgetting to add PingOhDearJob to not_tenant_aware_jobs in config/multitenancy.php causes silent failures.
    • Fix: Add:
      'not_tenant_aware_jobs' => [
          \Spatie\ScheduleMonitor\Jobs\PingOhDearJob::class,
      ],
      
  4. Log Bloat:

    • Unpruned logs can bloat the database. Monitor table size and adjust delete_log_items_older_than_days (default: 30).
  5. Anonymous Jobs:

    • Closures without monitorName() use the class name of the first argument (e.g., App\Jobs\SendReportJob). Override with:
      $schedule->call(fn () => $this->sendReport())->monitorName('send-report');
      

Debugging Tips

  • Failed Jobs:

    php artisan schedule-monitor:list --failed --verbose
    

    Check meta column in monitored_scheduled_task_log_items for exceptions (stored as JSON).

  • Oh Dear Ping Failures:

    • Verify OH_DEAR_API_TOKEN and OH_DEAR_MONITOR_ID are correct.
    • Test connectivity:
      curl -X POST https://ping.ohdear.app/api/v1/ping \
           -H "Authorization: Bearer YOUR_TOKEN" \
           -H "Content-Type: application/json" \
           -d '{"monitor_id": "YOUR_MONITOR_ID", "status": "ok"}'
      
  • Performance:

    • Use --keep-old for large schedules to avoid sync delays.
    • For high-volume jobs, batch Oh Dear pings by overriding PingOhDearJob:
      // app/Jobs/CustomPingOhDearJob.php
      use Spatie\ScheduleMonitor\Jobs\PingOhDearJob;
      
      class CustomPingOhDearJob extends PingOhDearJob {
          public function handle() {
              // Custom logic (e.g., batch pings)
              parent::handle();
          }
      }
      
      Update config:
      'ping_oh_dear_job' => App\Jobs\CustomPingOhDearJob::class,
      

Extension Points

  1. Custom Log Fields: Extend MonitoredScheduledTaskLogItem to add fields (e.g., user_id for user-triggered jobs):

    // app/Models/CustomLogItem.php
    use Spatie\ScheduleMonitor\Models\MonitoredScheduledTaskLogItem;
    
    class CustomLogItem extends MonitoredScheduledTaskLogItem {
        protected $casts = [
            'meta' => 'array',
            'user_id' => 'integer',
        ];
    }
    

    Update config:

    'monitored_scheduled_log_item' => App\Models\CustomLogItem::class,
    
  2. Webhook Notifications: Listen for log events via scheduled:monitored events:

    // app/Providers/EventServiceProvider.php
    use Spatie\ScheduleMonitor\Events\ScheduledTaskWasMonitored;
    
    protected $listen = [
        ScheduledTaskWasMonitored::class => [
            \App\Listeners\LogToWebhook::class,
        ],
    ];
    
  3. Slack Alerts: Integrate with schedule-monitor:list output using Laravel’s Artisan::call():

    $output = Artisan::call('schedule-monitor:list', ['--failed' => true]);
    $this->slack->send("Failed jobs: $output");
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport