diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md index 832d68f..4a115d0 100644 --- a/docs/RELEASE-NOTES.md +++ b/docs/RELEASE-NOTES.md @@ -4,6 +4,10 @@ ## [Unreleased] +### 수정 +- Top 클라이언트 IP/ID 토글 활성 상태 구분 및 표시 오류 수정 +- 쿼리 이력(메트릭 페이지)에 사용자 ID 컬럼 추가 + ## [2026-03-27] ### 추가 diff --git a/frontend/src/api/types.ts b/frontend/src/api/types.ts index e8b52ab..2970e5b 100644 --- a/frontend/src/api/types.ts +++ b/frontend/src/api/types.ts @@ -208,6 +208,7 @@ export interface QueryMetricRow { cache_hit_days: number db_query_days: number client_ip: string | null + client_id: string | null } export interface QueryMetricsPage { @@ -252,7 +253,8 @@ export interface TimeSeriesBucket { } export interface TopClient { - client_ip: string + client: string + client_ip?: string query_count: number avg_elapsed_ms: number } @@ -261,6 +263,7 @@ export interface QueryMetricsTimeSeries { buckets: TimeSeriesBucket[] topClients: TopClient[] granularity: 'HOURLY' | 'DAILY' + groupBy?: 'ip' | 'id' } export interface QueryMetricsParams { diff --git a/frontend/src/pages/ApiMetrics.tsx b/frontend/src/pages/ApiMetrics.tsx index 264ec8d..c3e95fc 100644 --- a/frontend/src/pages/ApiMetrics.tsx +++ b/frontend/src/pages/ApiMetrics.tsx @@ -136,6 +136,10 @@ export default function ApiMetrics() { key: 'client_ip', label: t('metrics.clientIp'), sortable: false, render: (row) => row.client_ip ? {row.client_ip} : '-', }, + { + key: 'client_id', label: 'ID', sortable: false, + render: (row) => row.client_id ? {row.client_id} : '-', + }, ] return ( diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 42db6a9..e2c6e06 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -326,30 +326,31 @@ export default function Dashboard() { {/* Top Clients */} - {queryTs.topClients.length > 0 && ( -
-
- {t('dashboard.topClients')} -
- - -
+
+
+ {t('dashboard.topClients')} +
+ +
+
+ {queryTs.topClients.length > 0 ? (
{queryTs.topClients.map((c, i) => { const maxCount = queryTs.topClients[0].query_count const pct = maxCount > 0 ? (c.query_count / maxCount) * 100 : 0 + const label = c.client ?? c.client_ip ?? '-' return ( -
- {c.client_ip ?? '-'} +
+ {label}
-
- )} + ) : ( +
+ {clientGroupBy === 'id' ? '사용자 ID 데이터가 없습니다' : '클라이언트 데이터가 없습니다'} +
+ )} +
) : (
{t('dashboard.noChartData')}
diff --git a/src/main/java/gc/mda/signal_batch/monitoring/controller/QueryMetricsController.java b/src/main/java/gc/mda/signal_batch/monitoring/controller/QueryMetricsController.java index 5afd5fc..eb18a0b 100644 --- a/src/main/java/gc/mda/signal_batch/monitoring/controller/QueryMetricsController.java +++ b/src/main/java/gc/mda/signal_batch/monitoring/controller/QueryMetricsController.java @@ -106,7 +106,7 @@ public class QueryMetricsController { zoom_level, requested_mmsi, unique_vessels, total_tracks, total_points, points_after_simplify, total_chunks, response_bytes, elapsed_ms, db_query_ms, simplify_ms, - cache_hit_days, db_query_days, client_ip + cache_hit_days, db_query_days, client_ip, client_id FROM signal.t_query_metrics """ + whereClause + " ORDER BY " + sortBy + " " + direction +