Today we've deployed our latest set of features! This includes a new "job" tab with a ton of extra context for failed jobs:

Ignition's job tab will display information about the failed job's class, its properties, connection, queue, tags, chained jobs and a lot more. This is all powered by Ignition version 2.16.0, which was released earlier today.
How does this work?
Under the hood, Ignition registers a couple "recorders" that hook into your Laravel application. For example, the DumpRecorder will capture and send dump statements to Flare as extra context when an exception takes place. There's also the LogRecorder and QueryRecorder that will... you guessed it: capture and send logs and queries to Flare.
So starting today, Ignition version 2.15.0 and above also includes a JobRecorder. The JobRecorder registers itself in your application and waits for a JobExceptionOccurred event:
public function register(): self
{
$this->app['events']->listen(JobExceptionOccurred::class, [$this, 'record']);
return $this;
}
Laravel sends out a JobExceptionOccurred event each time an exception is thrown within a job. Once the event is captured, we can find the failed queue Job in its $event->job property. The Job object also contains some basic information about the queue and connection that it failed on:
[
'name' => $this->job->resolveName(),
'connection' => $this->job->getConnectionName(),
'queue' => $this->job->getQueue(),
]
Other properties like the job's id, when it was pushed onto the queue, the tags associated with it and its actual parameters are all contained in the serialized payload.
Since these jobs need to be executed in a different worker process (e.g. on Laravel Horizon or using Amazon SQS), they've been serialized like this:
O:21:\"App\\Jobs\\TestFlareJob\":11:{s:27:\"\u0000App\\Jobs\\TestFlareJob\u0000name\";s:1:\"a\";s:3:\"job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:19:\"chainCatchCallbacks\";N;s:5:\"delay\";N;s:11:\"afterCommit\";N;s:10:\"middleware\";a:0:{}s:7:\"chained\";a:2:{i:0;s:276:\"O:21:\"App\\Jobs\\TestFlareJob\":11:{s:27:\"\u0000App\\Jobs\\TestFlareJob\u0000name\";s:1:\"b\";s:3:\"job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:19:\"chainCatchCallbacks\";N;s:5:\"delay\";N;s:11:\"afterCommit\";N;s:10:\"middleware\";a:0:{}s:7:\"chained\";a:0:{}}\";i:1;s:276:\"O:21:\"App\\Jobs\\TestFlareJob\":11:{s:27:\"\u0000App\\Jobs\\TestFlareJob\u0000name\";s:1:\"c\";s:3:\"job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:19:\"chainCatchCallbacks\";N;s:5:\"delay\";N;s:11:\"afterCommit\";N;s:10:\"middleware\";a:0:{}s:7:\"chained\";a:0:{}}\";}}
The get to the original data we need to deserialize this string. This will yield the original job object. We can then use class reflection to read its properties to an associative array:
$properties = collect((new ReflectionClass($command))->getProperties())
->mapWithKeys(function (ReflectionProperty $property) use ($command) {
$property->setAccessible(true);
return [$property->name => $property->getValue($command)];
});
That's it! This $properties array will be added as context to the Flare report and will soon show up in your Flare reports!
Continue reading
How Flare handles Livewire v4's single file components
Single file components are a great addition to Livewire v4, but their compiled output makes debugging harder. Here's how we taught Flare to map hashed file paths and line numbers back to your actual source files.
Ruben
Track frontend errors back to the exact commit
Swap the default random UUID for your git commit hash and trace every JavaScript error straight back to the deploy that caused it.
Dries
Subscribe to Backtrace, our quarterly Flare newsletter
No spam, just news & product updates