diff --git a/app/Models/DevTools/ApiRequestLog.php b/app/Models/DevTools/ApiRequestLog.php new file mode 100644 index 00000000..105254c3 --- /dev/null +++ b/app/Models/DevTools/ApiRequestLog.php @@ -0,0 +1,68 @@ + 'array', + 'request_body' => 'array', + 'request_query' => 'array', + 'response_status' => 'integer', + 'duration_ms' => 'integer', + 'user_id' => 'integer', + 'tenant_id' => 'integer', + 'created_at' => 'datetime', + ]; + + /** + * URL에서 엔드포인트 경로 추출 (쿼리스트링 제외) + */ + public function getEndpointAttribute(): string + { + return parse_url($this->url, PHP_URL_PATH) ?? $this->url; + } +} diff --git a/app/Services/ApiExplorer/ApiUsageService.php b/app/Services/ApiExplorer/ApiUsageService.php index 4f4650a2..31abf00a 100644 --- a/app/Services/ApiExplorer/ApiUsageService.php +++ b/app/Services/ApiExplorer/ApiUsageService.php @@ -3,7 +3,6 @@ namespace App\Services\ApiExplorer; use App\Models\DevTools\ApiDeprecation; -use App\Models\DevTools\ApiHistory; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; @@ -23,13 +22,18 @@ public function __construct( */ public function getUsageStats(): Collection { - return ApiHistory::select('endpoint', 'method') + // URL에서 경로만 추출 (도메인 및 쿼리스트링 제거) + // 예: https://api.sam.kr/api/v1/users?page=1 → /api/v1/users + // Note: DB facade 사용 (Eloquent accessor 충돌 방지) + return DB::table('api_request_logs') + ->selectRaw("REGEXP_REPLACE(SUBSTRING_INDEX(url, '?', 1), '^https?://[^/]+', '') as endpoint") + ->addSelect('method') ->selectRaw('COUNT(*) as call_count') ->selectRaw('MAX(created_at) as last_called_at') ->selectRaw('AVG(duration_ms) as avg_duration_ms') ->selectRaw('SUM(CASE WHEN response_status >= 200 AND response_status < 300 THEN 1 ELSE 0 END) as success_count') ->selectRaw('SUM(CASE WHEN response_status >= 400 THEN 1 ELSE 0 END) as error_count') - ->groupBy('endpoint', 'method') + ->groupByRaw("REGEXP_REPLACE(SUBSTRING_INDEX(url, '?', 1), '^https?://[^/]+', ''), method") ->orderByDesc('call_count') ->get(); } @@ -224,8 +228,10 @@ public function getStaleApis(int $days = 30): Collection { $cutoffDate = now()->subDays($days); - // 최근 호출된 API - $recentlyUsed = ApiHistory::select('endpoint', 'method') + // 최근 호출된 API (DB facade 사용 - Eloquent accessor 충돌 방지) + $recentlyUsed = DB::table('api_request_logs') + ->selectRaw("REGEXP_REPLACE(SUBSTRING_INDEX(url, '?', 1), '^https?://[^/]+', '') as endpoint") + ->addSelect('method') ->where('created_at', '>=', $cutoffDate) ->distinct() ->get() @@ -246,9 +252,10 @@ public function getStaleApis(int $days = 30): Collection */ public function getDailyTrend(int $days = 30): Collection { - return ApiHistory::select(DB::raw('DATE(created_at) as date')) + return DB::table('api_request_logs') + ->select(DB::raw('DATE(created_at) as date')) ->selectRaw('COUNT(*) as call_count') - ->selectRaw('COUNT(DISTINCT CONCAT(endpoint, "|", method)) as unique_endpoints') + ->selectRaw("COUNT(DISTINCT CONCAT(REGEXP_REPLACE(SUBSTRING_INDEX(url, '?', 1), '^https?://[^/]+', ''), '|', method)) as unique_endpoints") ->where('created_at', '>=', now()->subDays($days)) ->groupBy('date') ->orderBy('date')