Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Thijmen1992's avatar

Override queue worker

Hi all,

First time posting here so if I am at the wrong place, please let me know :-)

Currently, when running php artisan queue:work, the output is as following:

[2021-10-06 09:38:35][JtANf66QJ5qibMl9zDRwZdpXbblE0asO] Processing: App\Jobs\MyJob
[2021-10-06 09:38:35][JtANf66QJ5qibMl9zDRwZdpXbblE0asO] Processed:  App\Jobs\MyJob

What I would want

I want to change the output and move it to JSON output. JSON output because our logging system (DataDog) can then index it better and we can query DataDog in a way we want.

What I've tried

  1. Create own command
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Queue\Console\WorkCommand;

class MyWorkCommand extends WorkCommand
{

}

I register the command in Kernel.php. When running php artisan, I get the following output:

[2021-10-06T09:47:58.728967+00:00] local.ERROR: Unresolvable dependency resolving [Parameter #3 [ <required> callable $isDownForMaintenance ]] in class Illuminate\Queue\Worker {"exception":"[object] (Illuminate\Contracts\Container\BindingResolutionException(code: 0): Unresolvable dependency resolving [Parameter #3 [ <required> callable $isDownForMaintenance ]] in class Illuminate\Queue\Worker at /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:1053)"} []

This is being caused by the constructor of the WorkCommand:

    /**
     * Create a new queue work command.
     *
     * @param  \Illuminate\Queue\Worker  $worker
     * @param  \Illuminate\Contracts\Cache\Repository  $cache
     * @return void
     */
    public function __construct(Worker $worker, Cache $cache)
    {
        parent::__construct();

        $this->cache = $cache;
        $this->worker = $worker;
    }

Worker is being resolved but the constructor of Worker has a callable and is therefore not instantiated.

  1. Try to override the singleton in AppServiceProvider

In ArtisanServiceProvider there is a method called registerQueueWorkCommand. I copied the following code from there and pasted it in the boot method of my AppServiceProvider (tried the register method too without any luck):

 $this->app->singleton('command.queue.work', function ($app) {
            return new WorkOutputJsonCommand($app['queue.worker'], $app['cache.store']);
  });

My WorkOutputJsonCommand is as following:

use Illuminate\Contracts\Queue\Job;
use Illuminate\Queue\Console\WorkCommand;
use Illuminate\Support\Carbon;

class WorkOutputJsonCommand extends WorkCommand
{
    public function writeStatus(Job $job, $status, $type)
    {
        $this->output->writeln(sprintf(
            "<{$type}>[%s][%s] hello testing %s</{$type}> %s",
            Carbon::now()->format('Y-m-d H:i:s'),
            $job->getJobId(),
            str_pad("{$status}:", 11), $job->resolveName()
        ));
    }
}

This however doesn't work as well unfortunately. I placed the following snippet in my provider and the ArtisanServiceProvider:

dump(self::class . '::' . __FUNCTION__);

When I run php artisan queue:work, I get the following output:

"App\Providers\AppServiceProvider::boot"
"Illuminate\Foundation\Providers\ArtisanServiceProvider::registerQueueWorkCommand"

This tells me that my AppServiceProvider is being loaded before the ArtisanServiceProvider. However, in app.php config, my AppServiceProvider is being loaded after all the Illuminate service providers.

How can I achieve what I want?

0 likes
1 reply
johncartwright's avatar

I'm a little late to the show but I just wen't through the same journey to better control the output of the command workers for structured logs.

One important thing you missed here, and I hope there are better ways to handle this, is to ensure the ordering of the packages are explicitly registered.

// ensure the artisan service provider is registered first
$this->app->register(ArtisanServiceProvider::class);

// your new custom class
$this->app->singleton(WorkCommand::class, function ($app) {
    return new WorkCommand(
        $app['queue.worker'],
        $app['cache.store']
    );
});

...

and within your command, you can simply override the artisan commands by specifying the same signature.

use Illuminate\Queue\Console\WorkCommand as BaseWorkCommand;

class WorkCommand extends BaseWorkCommand
{
    protected $signature = 'queue:work
1 like

Please or to participate in this conversation.