with(['tenant', 'user']) ->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(); return view('api-logs.index', compact('logs', 'stats')); } /** * API 로그 상세 화면 */ public function show(int $id): View { $log = ApiRequestLog::with(['tenant', 'user'])->findOrFail($id); // 같은 그룹의 다른 요청들 $groupLogs = []; if ($log->group_id) { $groupLogs = ApiRequestLog::where('group_id', $log->group_id) ->where('id', '!=', $log->id) ->orderBy('created_at') ->get(); } return view('api-logs.show', compact('log', 'groupLogs')); } /** * 오래된 로그 삭제 (수동) */ public function prune() { $deleted = ApiRequestLog::pruneOldLogs(); return redirect()->route('dev-tools.api-logs.index') ->with('success', "{$deleted}개의 로그가 삭제되었습니다."); } }