feat: implement error notification system for developers

This commit is contained in:
Yoga Pangestu 2026-08-01 11:59:46 +07:00
parent 95be00c9d1
commit 93e69932e7
3 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,54 @@
<?php
namespace App\Listeners;
use App\Models\User;
use App\Notifications\ErrorNotification;
use Illuminate\Log\Events\MessageLogged;
class NotifyDeveloperOnError
{
/** @var list<string> */
protected array $notifyLevels = ['error', 'critical', 'alert', 'emergency'];
public function handle(MessageLogged $event): void
{
if (! in_array($event->level, $this->notifyLevels)) {
return;
}
$developers = User::role('Developer')->where('is_active', true)->get();
if ($developers->isEmpty()) {
return;
}
$title = '[ERROR] '.config('app.name');
$body = $this->formatBody($event);
foreach ($developers as $developer) {
$developer->notifications()->create([
'title' => $title,
'body' => $body,
]);
$developer->notify(new ErrorNotification(
title: $title,
body: $body,
level: $event->level,
));
}
}
protected function formatBody(MessageLogged $event): string
{
$message = $event->message;
if (isset($event->context['exception'])) {
$exception = $event->context['exception'];
$message .= ' - '.get_class($exception).': '.$exception->getMessage();
}
return $message;
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use NotificationChannels\WebPush\WebPushChannel;
use NotificationChannels\WebPush\WebPushMessage;
class ErrorNotification extends Notification implements ShouldQueue
{
use Queueable;
public function __construct(
public string $title,
public string $body,
public string $level = 'error',
public ?string $url = null,
) {}
/** @return list<class-string> */
public function via(object $notifiable): array
{
return [WebPushChannel::class];
}
public function toWebPush(object $notifiable, mixed $notification): WebPushMessage
{
$webPushMessage = (new WebPushMessage)
->title($this->title)
->icon('/icon-192x192.png')
->body($this->body);
if ($this->url) {
$webPushMessage->action('Lihat Detail', $this->url);
}
return $webPushMessage;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Providers;
use App\Listeners\NotifyDeveloperOnError;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Log\Events\MessageLogged;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
MessageLogged::class => [
NotifyDeveloperOnError::class,
],
];
public function boot(): void
{
parent::boot();
}
}