diff --git a/app/Http/Controllers/ApiLogController.php b/app/Http/Controllers/ApiLogController.php
index 4ccebcd7..753af441 100644
--- a/app/Http/Controllers/ApiLogController.php
+++ b/app/Http/Controllers/ApiLogController.php
@@ -13,7 +13,9 @@ class ApiLogController extends Controller
*/
public function index(Request $request): View
{
- $query = ApiRequestLog::query()->orderByDesc('created_at');
+ $query = ApiRequestLog::query()
+ ->with(['tenant', 'user'])
+ ->orderByDesc('created_at');
// 필터: HTTP 메서드
if ($request->filled('method')) {
@@ -37,6 +39,16 @@ public function index(Request $request): View
$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(),
@@ -56,9 +68,18 @@ public function index(Request $request): View
*/
public function show(int $id): View
{
- $log = ApiRequestLog::findOrFail($id);
+ $log = ApiRequestLog::with(['tenant', 'user'])->findOrFail($id);
- return view('api-logs.show', compact('log'));
+ // 같은 그룹의 다른 요청들
+ $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'));
}
/**
diff --git a/app/Models/ApiRequestLog.php b/app/Models/ApiRequestLog.php
index 11e71fb8..245d9252 100644
--- a/app/Models/ApiRequestLog.php
+++ b/app/Models/ApiRequestLog.php
@@ -21,11 +21,12 @@
* @property string|null $user_agent
* @property int|null $user_id
* @property int|null $tenant_id
+ * @property string|null $group_id
* @property \Carbon\Carbon $created_at
*/
class ApiRequestLog extends Model
{
- protected $table = 'api_request_logs';
+ protected $table = 'api_request_logs';
public $timestamps = false;
@@ -43,6 +44,7 @@ class ApiRequestLog extends Model
'user_agent',
'user_id',
'tenant_id',
+ 'group_id',
];
protected $casts = [
@@ -99,4 +101,57 @@ public static function pruneOldLogs(): int
{
return static::where('created_at', '<', now()->subDay())->delete();
}
+
+ /**
+ * 테넌트 관계
+ */
+ public function tenant()
+ {
+ return $this->belongsTo(\App\Models\Tenants\Tenant::class);
+ }
+
+ /**
+ * 사용자 관계
+ */
+ public function user()
+ {
+ return $this->belongsTo(\App\Models\User::class);
+ }
+
+ /**
+ * AI 분석용 요약 텍스트 생성
+ */
+ public function getAiAnalysisSummaryAttribute(): string
+ {
+ $responseData = json_decode($this->response_body, true);
+ $errorMessage = $responseData['message'] ?? $responseData['error'] ?? '';
+
+ $summary = "## API 에러 분석 요청\n\n";
+ $summary .= "### 요청 정보\n";
+ $summary .= "- **메서드**: {$this->method}\n";
+ $summary .= "- **URL**: {$this->url}\n";
+ $summary .= "- **라우트**: " . ($this->route_name ?? 'N/A') . "\n";
+ $summary .= "- **상태 코드**: {$this->response_status}\n";
+ $summary .= "- **응답 시간**: {$this->duration_ms}ms\n";
+ $summary .= "- **요청 시간**: {$this->created_at->format('Y-m-d H:i:s')}\n\n";
+
+ if ($this->request_body && count($this->request_body) > 0) {
+ $summary .= "### 요청 바디\n```json\n";
+ $summary .= json_encode($this->request_body, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
+ $summary .= "\n```\n\n";
+ }
+
+ $summary .= "### 응답 내용\n```json\n";
+ if ($responseData) {
+ $summary .= json_encode($responseData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
+ } else {
+ $summary .= $this->response_body ?? 'N/A';
+ }
+ $summary .= "\n```\n\n";
+
+ $summary .= "### 분석 요청\n";
+ $summary .= "위 API 에러의 원인을 분석하고 해결 방법을 제안해주세요.\n";
+
+ return $summary;
+ }
}
\ 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 f6a4d993..f2547054 100644
--- a/resources/views/api-logs/index.blade.php
+++ b/resources/views/api-logs/index.blade.php
@@ -87,6 +87,14 @@ class="w-full border rounded-lg px-3 py-2 text-sm">
+
+@if(request('group_id'))
+
+
그룹 ID: {{ request('group_id') }} 필터 적용 중
+
필터 해제
+
+@endif
+
@@ -96,15 +104,16 @@ class="w-full border rounded-lg px-3 py-2 text-sm">
| 메서드 |
URL |
상태 |
- 시간 |
- IP |
- User |
+ 응답 |
+ 테넌트 |
+ 사용자 |
+ 그룹 |
|
@forelse($logs as $log)
-
+
|
{{ $log->created_at->format('H:i:s') }}
|
@@ -113,7 +122,7 @@ class="w-full border rounded-lg px-3 py-2 text-sm">
{{ $log->method }}
-
+ |
{{ $log->path }}
|
@@ -125,10 +134,30 @@ class="w-full border rounded-lg px-3 py-2 text-sm">
{{ number_format($log->duration_ms) }}ms
|
- {{ $log->ip_address ?? '-' }}
+ @if($log->tenant)
+ {{ Str::limit($log->tenant->company_name, 10) }}
+ @else
+ -
+ @endif
|
- {{ $log->user_id ?? 'guest' }}
+ @if($log->user)
+ {{ $log->user->name ?? $log->user->email }}
+ @else
+ guest
+ @endif
+ |
+
+ @if($log->group_id)
+
+
+
+ @else
+ -
+ @endif
|
@@ -138,7 +167,7 @@ class="w-full border rounded-lg px-3 py-2 text-sm">
|
@empty
- |
+ |
로그가 없습니다.
|
diff --git a/resources/views/api-logs/show.blade.php b/resources/views/api-logs/show.blade.php
index 6d15fe1f..a5506225 100644
--- a/resources/views/api-logs/show.blade.php
+++ b/resources/views/api-logs/show.blade.php
@@ -13,6 +13,14 @@
API 로그 상세
+ @if($log->response_status >= 400)
+
+ @endif
@@ -49,7 +57,7 @@
-
+
라우트
{{ $log->route_name ?? '-' }}
@@ -59,16 +67,98 @@
{{ $log->ip_address ?? '-' }}
-
User ID
-
{{ $log->user_id ?? 'guest' }}
+
테넌트
+
+ @if($log->tenant)
+ {{ $log->tenant->company_name }} (#{{ $log->tenant_id }})
+ @else
+ {{ $log->tenant_id ?? '-' }}
+ @endif
+
-
Tenant ID
-
{{ $log->tenant_id ?? '-' }}
+
사용자
+
+ @if($log->user)
+ {{ $log->user->name ?? $log->user->email }} (#{{ $log->user_id }})
+ @else
+ {{ $log->user_id ? "#{$log->user_id}" : 'guest' }}
+ @endif
+
+
+
+
+@if($log->group_id && count($groupLogs) > 0)
+
+
+ 같은 그룹의 요청 ({{ count($groupLogs) }}개)
+
+ 전체 보기
+
+
+
+
+
+
+ | 시간 |
+ 메서드 |
+ URL |
+ 상태 |
+ 응답 |
+ |
+
+
+
+ @foreach($groupLogs as $gLog)
+
+ |
+ {{ $gLog->created_at->format('H:i:s.u') }}
+ |
+
+
+ {{ $gLog->method }}
+
+ |
+
+ {{ $gLog->path }}
+ |
+
+
+ {{ $gLog->response_status }}
+
+ |
+
+ {{ number_format($gLog->duration_ms) }}ms
+ |
+
+
+ 상세
+
+ |
+
+ @endforeach
+
+
+
+
+@endif
+
@if($log->user_agent)
@@ -125,4 +215,21 @@
@endif
-@endsection
\ No newline at end of file
+
+@if($log->response_status >= 400)
+
+
+
+
+@endif
+@endsection