From 93e69932e71c2c61d4d3d696ea03e71de6f7ff96 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Sat, 1 Aug 2026 11:59:46 +0700 Subject: [PATCH] feat: implement error notification system for developers --- app/Listeners/NotifyDeveloperOnError.php | 54 ++++++++++++++++++++++++ app/Notifications/ErrorNotification.php | 41 ++++++++++++++++++ app/Providers/EventServiceProvider.php | 21 +++++++++ 3 files changed, 116 insertions(+) create mode 100644 app/Listeners/NotifyDeveloperOnError.php create mode 100644 app/Notifications/ErrorNotification.php create mode 100644 app/Providers/EventServiceProvider.php diff --git a/app/Listeners/NotifyDeveloperOnError.php b/app/Listeners/NotifyDeveloperOnError.php new file mode 100644 index 0000000..8951f1b --- /dev/null +++ b/app/Listeners/NotifyDeveloperOnError.php @@ -0,0 +1,54 @@ + */ + 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; + } +} diff --git a/app/Notifications/ErrorNotification.php b/app/Notifications/ErrorNotification.php new file mode 100644 index 0000000..df3abd5 --- /dev/null +++ b/app/Notifications/ErrorNotification.php @@ -0,0 +1,41 @@ + */ + 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; + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php new file mode 100644 index 0000000..6e6b7ca --- /dev/null +++ b/app/Providers/EventServiceProvider.php @@ -0,0 +1,21 @@ + [ + NotifyDeveloperOnError::class, + ], + ]; + + public function boot(): void + { + parent::boot(); + } +}