attributes->set(self::StartedAtKey, microtime(true)); return $next($request); } /** * Der INSERT läuft erst nach gesendeter Antwort (terminable Middleware) und * verlängert damit nicht mehr die wahrgenommene Request-Dauer. Der Startwert * wird über die Request-Attribute übergeben, da `terminate()` auf einer * frischen Middleware-Instanz aufgerufen wird. */ public function terminate(Request $request, Response $response): void { $startedAt = (float) $request->attributes->get(self::StartedAtKey, microtime(true)); $this->writeLog($request, $response, $startedAt); } private function writeLog(Request $request, Response $response, float $startedAt): void { $token = $request->user()?->currentAccessToken(); $tokenId = $token instanceof PersonalAccessToken && (int) $token->getKey() > 0 ? (int) $token->getKey() : null; ApiUsageLog::query()->create([ 'user_id' => $request->user()?->id, 'personal_access_token_id' => $tokenId, 'method' => $request->method(), 'path' => '/'.$request->path(), 'route_name' => $request->route()?->getName(), 'status_code' => $response->getStatusCode(), 'ip_address' => $request->ip(), 'user_agent' => mb_substr((string) $request->userAgent(), 0, 512), 'duration_ms' => (int) round((microtime(true) - $startedAt) * 1000), 'requested_at' => now(), ]); } }