hasAny(['method', 'status', 'search', 'group_id', 'tenant_id']); $query = ApiRequestLog::query() ->with(['tenant', 'user']); if ($hasFilter) { $query->orderBy('created_at'); // 오래된 순 } else { $query->orderByDesc('created_at'); // 최신순 } // 필터: HTTP 메서드 if ($request->filled('method')) { $query->where('method', $request->method); } // 필터: 상태 코드 if ($request->filled('status')) { $status = $request->status; if ($status === '2xx') { $query->whereBetween('response_status', [200, 299]); } elseif ($status === '4xx') { $query->whereBetween('response_status', [400, 499]); } elseif ($status === '5xx') { $query->whereBetween('response_status', [500, 599]); } } // 필터: URL 검색 if ($request->filled('search')) { $query->where('url', 'like', '%' . $request->search . '%'); } // 필터: 그룹 ID if ($request->filled('group_id')) { $query->where('group_id', $request->group_id); } // 필터: 테넌트 if ($request->filled('tenant_id')) { $query->where('tenant_id', $request->tenant_id); } // 통계 $stats = [ 'total' => ApiRequestLog::count(), 'success' => ApiRequestLog::whereBetween('response_status', [200, 299])->count(), 'client_error' => ApiRequestLog::whereBetween('response_status', [400, 499])->count(), 'server_error' => ApiRequestLog::whereBetween('response_status', [500, 599])->count(), 'avg_duration' => (int) ApiRequestLog::avg('duration_ms'), ]; $logs = $query->paginate(50)->withQueryString(); // 현재 페이지 로그들의 그룹별 개수 조회 $groupIds = $logs->pluck('group_id')->filter()->unique()->values()->toArray(); $groupCounts = []; if (!empty($groupIds)) { $groupCounts = ApiRequestLog::whereIn('group_id', $groupIds) ->selectRaw('group_id, COUNT(*) as count') ->groupBy('group_id') ->pluck('count', 'group_id') ->toArray(); } return view('api-logs.index', compact('logs', 'stats', 'groupCounts')); } /** * API 로그 상세 화면 */ public function show(int $id): View { $log = ApiRequestLog::with(['tenant', 'user'])->findOrFail($id); // 같은 그룹의 다른 요청들 (오래된 순) $groupLogs = collect(); $groupMethodCounts = []; if ($log->group_id) { $groupLogs = ApiRequestLog::where('group_id', $log->group_id) ->where('id', '!=', $log->id) ->orderBy('created_at') // 오래된 순 ->get(); // 메서드별 개수 집계 $groupMethodCounts = $groupLogs->groupBy('method') ->map(fn($items) => $items->count()) ->sortKeys() ->toArray(); } return view('api-logs.show', compact('log', 'groupLogs', 'groupMethodCounts')); } /** * 오래된 로그 삭제 (수동) */ public function prune() { $deleted = ApiRequestLog::pruneOldLogs(); return redirect()->route('dev-tools.api-logs.index') ->with('success', "{$deleted}개의 로그가 삭제되었습니다."); } /** * 모든 로그 삭제 */ public function truncate() { $deleted = ApiRequestLog::truncate(); return redirect()->route('dev-tools.api-logs.index') ->with('success', '모든 로그가 삭제되었습니다.'); } }