Name your Laravel Horizon workers for easier debugging at the CLI

Want to help support this blog? Try out Oh Dear, the best all-in-one monitoring tool for your entire website, co-founded by me (the guy that wrote this blogpost). Start with a 10-day trial, no strings attached.

We offer uptime monitoring, SSL checks, broken links checking, performance & cronjob monitoring, branded status pages & so much more. Try us out today!

Profile image of Mattias Geniar

Mattias Geniar, December 19, 2019

Follow me on Twitter as @mattiasgeniar

As part of our Oh Dear! monitoring service, we run workers. A lot of workers. Every site uptime check is a new worker, every broken links job is a new worker, every certificate check is a- you get the idea.

We use Laravel Horizon extensively for this. We dispatch jobs on the queue, Horizon picks them of and processes them.

By default, if we were to look at one of our servers, the htop view would be this.

Laravel Horizon: default process name

We see lots of php artisan horizon:work with some queue parameters attached to them. This is a sane default and will allow you to quickly see what kind of processes are eating your CPU or memory.

By looking at the name, you can see on what queue they were dispatched and you can make some educated guesses from there on.

Normally, I would return to my trusty strace utility to see what a particular process would be doing. But PHP offers us a better way in the form of cli_set_process_title().

It does exactly what’s in the function name: it allows you to set a custom process title if your PHP process was started via CLI (this won’t work in mod_php or php-fpm, luckily).

To make my life easier to debug, I applied this to our workers and this is what they look like now.

Laravel Horizon: default process name

Notice anything different?

Each job is still a Laravel Horizon worker, but the process name includes the URL of the site that’s being monitored as well as the team name that it belongs to.

The implementation is super easy and I encourage you to see if you can implement it yourself, if only to thank yourself later if you’re troubleshooting high CPU usages.

In our helpers-file, I added a new global function.

<?php
function setHorizonProcessName(string $url, string $team, string $type)
{
    @cli_set_process_title('php artisan horizon:work '. $type .' '. $url .' (team: '. $team .')');
}

Now in every job we dispatch, I call that function.

<?php
class PerformRunJob implements ShouldQueue
{
    // Code removed for readability [...]

    public function handle()
    {
        setHorizonProcessName(
            $this->url,
            $this->teamName,
            $type
        );

        // ...
    }
}

I had to add some error suppression to the cli_set_process_title because Mac apparently no longer supports this and that’s where our primary development is.

This just makes it be quiet on Mac and functional on Linux, just the way we like it. 😉



Want to subscribe to the cron.weekly newsletter?

I write a weekly-ish newsletter on Linux, open source & webdevelopment called cron.weekly.

It features the latest news, guides & tutorials and new open source projects. You can sign up via email below.

No spam. Just some good, practical Linux & open source content.