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

GM's avatar
Level 8

Logging to Mattermost custom driver

Time to give back to the community. The following is a simple guide to using Mattermost a log channel.

First set up your Mattermost side of things

The laravel side all starts with the configuration. I like to set a few things in the .env file

LOG_CHANNEL=stack
MATTERMOST_LOG_URL=https://mm.example.com:40404/hooks/234v7d67nggstfg5qgj4xtae7pkta
MATTERMOST_HELPDESK_URL=https://mm.example.com:40404/hooks/dxq3j6kxrigkmna9qswmbgu1my
MATTERMOST_ICON=http://www.example.com/hermes.png
MATTERMOST_USERNAME=Hermes

Putting the webhook URLs in to my .env allows me to target different channels on the same or different mattermost servers.

in config/logging.php I can then configure the logging how I want

'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['single', 'mattermost_log'],
        ],
        'single' => [
            'driver' => 'single',
            'path' => storage_path('logs/laravel.log'),
            'level' => 'debug',
        ],
        'mattermost_log' => [
            'driver' => 'custom',
            'via'    => App\Logging\CreateCustomLogger::class,
            'url'    => env( 'MATTERMOST_LOG_URL'),
            'level'  => 'error',
        ],

        'helpdesk' => [
            'driver' => 'custom',
            'via'    => App\Logging\CreateCustomLogger::class,
            'url'    => env( 'MATTERMOST_HELPDESK_URL'),
            'level'  => 'info',
        ],

Next we need to create out custom logger and handler... I create a new directory under app called Logging and in there I have CreateCustomLogger.php

<?php

namespace App\Logging;

use Monolog\Logger;

class CreateCustomLogger
{
    /**
     * Create a custom Monolog instance.
     *
     * @param  array $config
     *
     * @return \Monolog\Logger
     */
    public function __invoke(array $config)
    {
        return new Logger(
            env('APP_NAME'),
            [
                new MattermostHandler(
                    $config['url'],
                    $config['level']
                ),
            ]
        );
    }

and MattermostHandler.php

<?php

namespace App\Logging;

use GuzzleHttp\Client;
use Monolog\Logger;
use Monolog\Handler\AbstractProcessingHandler;
use Log;

class MattermostHandler extends AbstractProcessingHandler
{
    private $webHookUrl;
    private $client;

    public function __construct($webHookUrl, $level = Logger::DEBUG, $bubble = true, $client = null)
    {
        parent::__construct($level, $bubble);

        $this->webHookUrl = $webHookUrl;
        $this->client     = ($client) ?: new Client();
    }

    public function write(array $record)
    {
        $this->client->request('POST', $this->webHookUrl, [
            'form_params' => [
                'payload' => json_encode(
                    [
                        'username' => env('MATTERMOST_USERNAME'),
                        'icon_url' => env('MATTERMOST_ICON'),
                        'text'     => $record['message'],
                    ]
                ),
            ],
        ]);
    }
}

Thats it. Now I can call

Log::error('Something really important');

and it will log to both the laravel.log file and my mattermost log channel.

Or I can call

Log::channel('helpdesk')->info('This is a helpdesk message');

to send a message to the Mattermost helpdesk channel.

for example:

    Mail::raw($data['message'], function ($m) use ($data) {
            $m->to(Engagement::supportAddress())->subject(__('Support Request: ') $data['subject']);

            $m->replyTo($data['from']);
        });

        $mattermost_text = "#### Helpdesk Support Request " . date('l jS \of F Y h:i:s A') . "\n\n" .
            "Subject: " . $data['subject'] . "\n" .
            "Message: " . $data['message'] . "\n " .
            "Reply to: " . $data['from'] . "\n";
        Log::channel('helpdesk')->info($mattermost_text);

Formatting what the message looks like is fairly easy and covered in https://docs.mattermost.com/developer/webhooks-incoming.html, but be aware that formatting only works on HTML devices... my iOS device still just shows raw text rather than nicely formatted tables.

0 likes
1 reply
edwardkarlsson's avatar

Sweet!!! Thanks for your contribution. This helped in my upgrade process to 5.6... I, for some reason, thought that I could specify a driver => 'papertrail' and that it would still magically work... but you helped me to realize that I had to use the driver => 'custom'.

I was still able to have a specific name on the 'via' => App\Logging\CreatePapertrailLogger::class.

Please or to participate in this conversation.