phplaravellaravel-horizon

How to combine default and custom tags in Laravel Horizon job?


I'm using Laravel Horizon to monitor my queued jobs. I know that Horizon automatically assigns default tags (e.g., based on the job's class name or Eloquent model IDs), but I want to add custom tags on top of those.

However, I'm not sure how to properly combine my own custom tags with the default tags provided by Horizon.

Here's a simplified version of my job class:

use Illuminate\Contracts\Queue\ShouldQueue;

class ProcessReport implements ShouldQueue
{
    public function handle()
    {
        // Job logic
    }

    public function tags(): array
    {
        return ['custom:report', 'user:' . $this->userId];
    }
}

In this example, Horizon will use only the custom tags returned by the tags() method and ignore the default ones.

What I want:

I'd like to preserve the default Horizon tags (such as the job class name or model-related tags) and add my own tags on top of them.

Is there a way to access Horizon's default tag logic and combine it with my custom tags?


Solution

  • If we look at the vendor/laravel/horizon/src/Tags.php file and into the for method, which is used to determine the tags of a job, we can extract the following piece of logic:

    return static::modelsFor(static::targetsFor($job))->map(function ($model) {
        return get_class($model).':'.$model->getKey();
    })->all();
    

    In respect to this, we can now use that tags object like so to automatically map model tags:

    use Laravel\Horizon\Tags;
    
    /**
     * @return array
     */
    public function tags(): array
    {
        $otherTags = ['test-tag-1', 'test-tag-2', static::class];
    
        return array_merge(Tags::modelsFor(Tags::targetsFor($this))->map(function ($model) {
            return get_class($model).':'.$model->getKey();
        })->all(), $otherTags);
    }
    

    Note you may still need to add static:class here depending on your use case but a lot of this logic can be moved into a parent class / trait.