$message, 'actor_id' => optional(auth()->user())->getAuthIdentifier(), 'ip' => $request?->ip(), 'user_agent' => $request?->userAgent(), 'request_id' => $request?->headers->get('X-Request-Id'), 'performed_at' => now()->toIso8601String(), ], $context); $payload['request_id'] = $payload['request_id'] ?? Str::uuid()->toString(); Log::channel(self::CHANNEL)->log($level, $message, $payload); } /** * Tulis log request/response agar debugging controller lebih cepat. */ public function logHttp(string $action, Request $request, mixed $response = null, array $context = [], string $level = 'info'): void { $payload = [ 'action' => $action, 'actor_id' => optional(auth()->user())->getAuthIdentifier(), 'request_id' => $request->headers->get('X-Request-Id') ?? Str::uuid()->toString(), 'performed_at' => now()->toIso8601String(), 'http' => [ 'method' => $request->getMethod(), 'uri' => $request->fullUrl(), 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), 'body' => $this->maskSensitiveFields($request->all()), ], ]; if ($response instanceof Response) { $payload['http']['response'] = $this->normalizeResponse($response); } if (! empty($context)) { $payload['context'] = $context; } Log::channel(self::CHANNEL)->log($level, $action, $payload); } private function maskSensitiveFields(array $input): array { foreach ($input as $key => &$value) { if (in_array($key, $this->hiddenRequestFields, true)) { $value = '[MASKED]'; } } return $input; } private function normalizeResponse(Response $response): array { $body = $response instanceof JsonResponse ? $response->getData(true) : $response->getContent(); if (is_string($body) && strlen($body) > 2000) { $body = Str::limit($body, 2000, '...[terpotong]'); } return [ 'status' => $response->getStatusCode(), 'body' => $body, ]; } }