diff --git a/frontend/src/api/admin/ops.ts b/frontend/src/api/admin/ops.ts index f52227ca..3a5484df 100644 --- a/frontend/src/api/admin/ops.ts +++ b/frontend/src/api/admin/ops.ts @@ -362,6 +362,45 @@ export async function getAccountAvailabilityStats(platform?: string, groupId?: n return data } +export interface OpsRateSummary { + current: number + peak: number + avg: number +} + +export interface OpsRealtimeTrafficSummary { + window: string + start_time: string + end_time: string + platform: string + group_id?: number | null + qps: OpsRateSummary + tps: OpsRateSummary +} + +export interface OpsRealtimeTrafficSummaryResponse { + enabled: boolean + summary: OpsRealtimeTrafficSummary | null + timestamp?: string +} + +export async function getRealtimeTrafficSummary( + window: string, + platform?: string, + groupId?: number | null +): Promise { + const params: Record = { window } + if (platform) { + params.platform = platform + } + if (typeof groupId === 'number' && groupId > 0) { + params.group_id = groupId + } + + const { data } = await apiClient.get('/admin/ops/realtime-traffic', { params }) + return data +} + /** * Subscribe to realtime QPS updates via WebSocket. * @@ -957,6 +996,7 @@ export const opsAPI = { getErrorDistribution, getConcurrencyStats, getAccountAvailabilityStats, + getRealtimeTrafficSummary, subscribeQPS, listErrorLogs, getErrorLogDetail, diff --git a/frontend/src/views/admin/ops/OpsDashboard.vue b/frontend/src/views/admin/ops/OpsDashboard.vue index 15f269c2..f6712352 100644 --- a/frontend/src/views/admin/ops/OpsDashboard.vue +++ b/frontend/src/views/admin/ops/OpsDashboard.vue @@ -13,11 +13,6 @@ ('closed') -const wsReconnectInMs = ref(null) -const wsHasData = ref(false) -let unsubscribeQPS: (() => void) | null = null - let dashboardFetchController: AbortController | null = null let dashboardFetchSeq = 0 @@ -201,50 +186,6 @@ function abortDashboardFetch() { } } -function stopQPSSubscription(options?: { resetMetrics?: boolean }) { - wsStatus.value = 'closed' - wsReconnectInMs.value = null - if (unsubscribeQPS) unsubscribeQPS() - unsubscribeQPS = null - - if (options?.resetMetrics) { - realTimeQPS.value = 0 - realTimeTPS.value = 0 - wsHasData.value = false - } -} - -function startQPSSubscription() { - stopQPSSubscription() - unsubscribeQPS = opsAPI.subscribeQPS( - (payload) => { - if (payload && typeof payload === 'object' && payload.type === 'qps_update' && payload.data) { - realTimeQPS.value = payload.data.qps || 0 - realTimeTPS.value = payload.data.tps || 0 - wsHasData.value = true - } - }, - { - onStatusChange: (status) => { - wsStatus.value = status - if (status === 'connected') wsReconnectInMs.value = null - }, - onReconnectScheduled: ({ delayMs }) => { - wsReconnectInMs.value = delayMs - }, - onFatalClose: (event) => { - // Server-side feature flag says realtime is disabled; keep UI consistent and avoid reconnect loops. - if (event && event.code === OPS_WS_CLOSE_CODES.REALTIME_DISABLED) { - adminSettingsStore.setOpsRealtimeMonitoringEnabledLocal(false) - stopQPSSubscription({ resetMetrics: true }) - } - }, - // QPS updates may be sparse in idle periods; keep the timeout conservative. - staleTimeoutMs: 180_000 - } - ) -} - const readQueryString = (key: string): string => { const value = route.query[key] if (typeof value === 'string') return value @@ -626,12 +567,6 @@ onMounted(async () => { // Load thresholds configuration loadThresholds() - if (adminSettingsStore.opsRealtimeMonitoringEnabled) { - startQPSSubscription() - } else { - stopQPSSubscription({ resetMetrics: true }) - } - if (opsEnabled.value) { await fetchData() } @@ -648,19 +583,6 @@ async function loadThresholds() { } onUnmounted(() => { - stopQPSSubscription() abortDashboardFetch() }) - -watch( - () => adminSettingsStore.opsRealtimeMonitoringEnabled, - (enabled) => { - if (!opsEnabled.value) return - if (enabled) { - startQPSSubscription() - } else { - stopQPSSubscription({ resetMetrics: true }) - } - } -)