config->get('loghandler', []); if (! ($settings['enabled'] ?? false)) { return; } $endpoint = (string) ($settings['endpoint'] ?? ''); $token = (string) ($settings['token'] ?? ''); if ($endpoint === '' || $token === '') { return; } $payload = $this->buildPayload($record, $settings); $retryTimes = (int) ($settings['retry_times'] ?? 0); for ($attempt = 0; $attempt <= $retryTimes; $attempt++) { try { $this->httpClient->request('POST', $endpoint, [ 'headers' => [ 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$token, 'Content-Type' => 'application/json', ], 'json' => $payload, ]); break; } catch (GuzzleException|Throwable) { if ($attempt === $retryTimes) { return; } } } } private function buildPayload(LogRecord $record, array $settings): array { $exception = $this->resolveThrowable($record); return [ 'source' => (string) ($settings['source'] ?? 'Laravel'), 'error' => $exception instanceof Throwable ? $exception->getMessage() : (string) $record->message, 'type' => $this->resolveType($record, $exception), 'file' => $this->resolveFile($exception, $record), 'line' => $this->resolveLine($exception, $record), 'trace' => $this->resolveTrace($exception, $record, (bool) ($settings['include_trace'] ?? false)), ]; } private function resolveThrowable(LogRecord $record): ?Throwable { $context = $record->context; $exception = $context['exception'] ?? null; return $exception instanceof Throwable ? $exception : null; } private const ERROR_LEVEL_MAP = [ E_ERROR => 'E_ERROR', E_WARNING => 'E_WARNING', E_PARSE => 'E_PARSE', E_NOTICE => 'E_NOTICE', E_CORE_ERROR => 'E_CORE_ERROR', E_CORE_WARNING => 'E_CORE_WARNING', E_COMPILE_ERROR => 'E_COMPILE_ERROR', E_COMPILE_WARNING => 'E_COMPILE_WARNING', E_USER_ERROR => 'E_USER_ERROR', E_USER_WARNING => 'E_USER_WARNING', E_USER_NOTICE => 'E_USER_NOTICE', E_STRICT => 'E_STRICT', E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', E_DEPRECATED => 'E_DEPRECATED', E_USER_DEPRECATED => 'E_USER_DEPRECATED', ]; private function resolveType(LogRecord $record, ?Throwable $exception): string { if ($exception instanceof ErrorException) { return self::ERROR_LEVEL_MAP[$exception->getSeverity()] ?? 'ErrorException'; } if ($exception instanceof Throwable) { return $exception::class; } return 'E_'.strtoupper($record->level->getName()); } private function resolveFile(?Throwable $exception, LogRecord $record): string { if ($exception instanceof Throwable) { return $exception->getFile(); } return (string) ($record->context['file'] ?? 'unknown'); } private function resolveLine(?Throwable $exception, LogRecord $record): string { if ($exception instanceof Throwable) { return (string) $exception->getLine(); } if (isset($record->context['line'])) { return (string) $record->context['line']; } return '0'; } private function resolveTrace(?Throwable $exception, LogRecord $record, bool $includeTrace): string { if (! $includeTrace) { return ''; } if ($exception instanceof Throwable) { return $exception->getTraceAsString(); } return (string) ($record->context['trace'] ?? ''); } }