reportable(function (Throwable $e) { $this->handleExceptionAlert($e); }); $this->renderable(function (Throwable $e) { $this->handleExceptionAlert($e); }); } private function handleExceptionAlert(Throwable $e): void { if (! $this->shouldAlertException($e)) { return; } try { $alertService = app(AlertService::class); $errorMessage = $e->getMessage() ?: $e::class; $alertService->sendCriticalError($errorMessage, $e); $this->trackErrorRate(); Log::channel('emergency')->error('Critical exception reported via alert', [ 'exception' => $e::class, 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), ]); } catch (\Exception $alertException) { Log::error('Failed to send exception alert: ' . $alertException->getMessage()); } } private function shouldAlertException(Throwable $e): bool { if (! app()->isBooted()) { return false; } if (! (bool) setting('alert_errors_enabled', true)) { return false; } $criticalExceptions = [ QueryException::class, RconConnectionException::class, ]; foreach ($criticalExceptions as $criticalException) { if ($e instanceof $criticalException) { return true; } } if ($this->isHighErrorRate()) { return true; } $minSeverity = setting('alert_min_severity', 'error'); return $this->isSeverityHighEnough($e, $minSeverity); } private function trackErrorRate(): void { if (! app()->isBooted()) { return; } $key = self::CACHE_KEY_ERROR_COUNT . now()->format('YmdHi'); $count = Cache::get($key, 0); Cache::put($key, $count + 1, self::ERROR_COUNT_DURATION); } private function isHighErrorRate(): bool { if (! app()->isBooted()) { return false; } $threshold = (int) setting('alert_error_threshold', 10); $key = self::CACHE_KEY_ERROR_COUNT . now()->format('YmdHi'); $count = Cache::get($key, 0); return $count >= $threshold; } private function isSeverityHighEnough(Throwable $e, string $minSeverity): bool { $severityLevel = [ 'info' => 0, 'warning' => 1, 'error' => 2, 'critical' => 3, ]; $exceptionSeverity = $this->determineExceptionSeverity($e); $minLevel = $severityLevel[$minSeverity] ?? 2; return $exceptionSeverity >= $minLevel; } private function determineExceptionSeverity(Throwable $e): int { if ($e instanceof \Error) { return 3; } if ($e instanceof ValidationException) { return 0; } if ($e instanceof AuthenticationException) { return 1; } if ($e instanceof AuthorizationException) { return 1; } return 2; } }