diff --git a/app/Http/Controllers/ApiLogController.php b/app/Http/Controllers/ApiLogController.php index 753af441..4b8a2520 100644 --- a/app/Http/Controllers/ApiLogController.php +++ b/app/Http/Controllers/ApiLogController.php @@ -60,7 +60,18 @@ public function index(Request $request): View $logs = $query->paginate(50)->withQueryString(); - return view('api-logs.index', compact('logs', 'stats')); + // 현재 페이지 로그들의 그룹별 개수 조회 + $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')); } /** @@ -75,7 +86,7 @@ public function show(int $id): View if ($log->group_id) { $groupLogs = ApiRequestLog::where('group_id', $log->group_id) ->where('id', '!=', $log->id) - ->orderBy('created_at') + ->orderByDesc('created_at') ->get(); } @@ -92,4 +103,15 @@ public function prune() 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', '모든 로그가 삭제되었습니다.'); + } } \ No newline at end of file diff --git a/resources/views/api-logs/index.blade.php b/resources/views/api-logs/index.blade.php index f2547054..2d3f7554 100644 --- a/resources/views/api-logs/index.blade.php +++ b/resources/views/api-logs/index.blade.php @@ -7,10 +7,16 @@
| 시간 | -메서드 | +시간 | +메서드 | URL | -상태 | -응답 | -테넌트 | -사용자 | -그룹 | -+ | 상태 | +응답 | +테넌트 | +사용자 | +그룹 | +|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + | ||||||||||||||||
| {{ $log->created_at->format('H:i:s') }} | -+ | {{ $log->method }} | -- {{ $log->path }} + |
+ {{ $log->path }}
+ @php
+ $params = $log->request_body ?: $log->request_query ?: [];
+ if (is_array($params) && !empty($params)) {
+ $paramPairs = [];
+ foreach ($params as $key => $value) {
+ if (is_array($value)) {
+ $value = json_encode($value, JSON_UNESCAPED_UNICODE);
+ }
+ $paramPairs[] = $key . '=' . Str::limit((string)$value, 20);
+ }
+ $paramSummary = implode(', ', $paramPairs);
+ } else {
+ $paramSummary = '';
+ }
+ @endphp
+ @if(!empty($paramSummary))
+
+ {{ $paramSummary }}
+
+ @endif
|
- + | {{ $log->response_status }} | -+ | {{ number_format($log->duration_ms) }}ms | -+ | @if($log->tenant) {{ Str::limit($log->tenant->company_name, 10) }} @else - @endif | -+ | @if($log->user) {{ $log->user->name ?? $log->user->email }} @else guest @endif | -- @if($log->group_id) + | + @if($log->group_id && ($groupCounts[$log->group_id] ?? 0) >= 2) + class="text-purple-600 hover:text-purple-800" title="{{ $log->group_id }} ({{ $groupCounts[$log->group_id] }}개)"> + {{ $groupCounts[$log->group_id] }} @else - @endif | -- - 상세 - + |
+
+ @if($log->response_status >= 400)
+
+ @endif
+
+
+
+
+ |
+
|
+
+
+
+
+
+ 요청 헤더+
+
+
+ @foreach($log->request_headers ?? [] as $key => $values)
+
+
+ {{ $key }}:
+ {{ is_array($values) ? implode(', ', $values) : $values }}
+
+ @endforeach
+
+
+ 응답 바디+
+ @php
+ $responseData = json_decode($log->response_body, true);
+ if ($responseData !== null) {
+ $displayResponse = json_encode($responseData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
+ } else {
+ $displayResponse = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function($m) {
+ return mb_convert_encoding(pack('H*', $m[1]), 'UTF-8', 'UTF-16BE');
+ }, $log->response_body ?? '');
+ $displayResponse = str_replace('\\/', '/', $displayResponse);
+ }
+ @endphp
+
+ {{ Str::limit($displayResponse, 2000) }}
+ |
||||||||||||||||