Flare's new "job" tab knows all about your failed jobs
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!