rap-2-h
rap-2-h

Reputation: 31948

Send a slack notification every time Log::error is triggered

Using Laravel 5, I want to be notified (on slack but it does not matter) every time Log::error (or similar) is triggered, by a direct call to this method or by the default ExceptionHandler calling report method. I think I have to extends default Laravel's Log system but I'm not sure. What's the (best) "laravel way" to do this ? (without changing every Log::error calls in my whole code).

First, I thought I only have to change Log Facade to one other but it will not handle the ExceptionHandler (i.e. on 500 errors due to uncaught Exception). One other solution could be add some code directly in the ExceptionHandler, but it will not be triggered if I report an error by Log::error() or some other way (app('logger')->error(), logger()->error(), etc.).

Upvotes: 11

Views: 22357

Answers (3)

Sapnesh Naik
Sapnesh Naik

Reputation: 11636

For Laravel 5.6 and above:

Laravel suppports slack driver for logging beginning with 5.6. Configure your slack channel in config/logging.php like so:

'slack' => [
    'driver' => 'slack',
    'url' => env('LOG_SLACK_WEBHOOK_URL'),
    'username' => 'Laravel Log',
    'emoji' => ':boom:',
    'level' => 'critical',
],

Now all the log messages which have an importance critical or above will automatically logged to slack channel.

You can also log to slack channel specifically:

Log::channel('slack')->info('Something happened!');

More info in Laravel logging and Slack incoming webhooks.

Upvotes: 15

user1669496
user1669496

Reputation: 33048

Edit: Broken as of Laravel 5.6

The Log facade is really just a wrapper for an underlying instance of Monolog. The good news is Monolog comes with support for Slack. You just need to tell Monolog to use it.

With that said, everything can be setup in 3 lines of code.

$monolog = \Log::getMonolog();
$slackHandler = new \Monolog\Handler\SlackHandler('your-token', '#your-channel', 'Monolog', true, null, \Monolog\Logger::ERROR);
$monolog->pushHandler($slackHandler);

Then to get this running, you can either create your own service provider for it or just drop it in AppServiceProvider's boot method.

You may want to look at the source code for SlackHandler just in case there are more options the constructor takes which you would need to use.

Now whenever you \Log::error('some error');, that error's message will be sent to the Slack channel you have setup. Please note this "bubbles up" which means it will be sent to the Slack channel for any logging done error and up, error, critical, alert, and emergency. Set the bubble parameter to false if you only want it to log errors.

Upvotes: 20

Maxim Lanin
Maxim Lanin

Reputation: 4531

You can listen to illuminate.log [String $level, String $message, Array $context] event. If $level equals error, you will send notification.

Define event listener in your EventServiceProvider

protected $listen = [
    'illuminate.log' => [
        'App\Listeners\LogEventListener'
    ]
];

This will tell Laravel to fire LogEventListener when illuminate.log event is fired.

Then create this listener:

namespace App\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class LogEventListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  DeployDisabledEvent  $event
     * @return void
     */
    public function handle($event)
    {
        if ($event->type == 'error') {
            $this->notifyViaSlack($event->message, $event->context);
        }
    }

    /**
     * Send Slack notification.
     *
     * @param  string  $message
     * @param  string  $context
     * @return void
     */
    protected function notifyViaSlack($message, $context)
    {
        /*
         * Slack notification logic
         */
    }
}

Upvotes: 7

Related Questions