feat(report): add slow API ranking module for admin

This commit is contained in:
2026-02-07 12:19:53 +08:00
parent a50294933b
commit 592d48dde0
24 changed files with 151 additions and 53 deletions

View File

@@ -17,7 +17,7 @@ import {
import { fetchFeedbackStats } from '../api/feedbacks'
import { fetchEmailStats } from '../api/email'
import { fetchDockerStats, fetchRunningTasks, fetchServerInfo, fetchTaskStats } from '../api/tasks'
import { fetchDockerStats, fetchRequestMetrics, fetchRunningTasks, fetchServerInfo, fetchTaskStats } from '../api/tasks'
import { fetchBrowserPoolStats } from '../api/browser_pool'
import { fetchSystemConfig } from '../api/system'
import MetricGrid from '../components/MetricGrid.vue'
@@ -37,6 +37,7 @@ const serverInfo = ref(null)
const dockerStats = ref(null)
const browserPoolStats = ref(null)
const systemConfig = ref(null)
const requestMetrics = ref(null)
const queueTab = ref('running')
function recordUpdatedAt() {
@@ -67,6 +68,23 @@ function percentText(value) {
return `${Math.round(parsePercent(value))}%`
}
function formatMs(value) {
const n = Number(value)
if (!Number.isFinite(n) || n < 0) return '-'
if (n >= 100) return `${Math.round(n)}ms`
return `${n.toFixed(1)}ms`
}
function formatUnixTime(value) {
const ts = Number(value)
if (!Number.isFinite(ts) || ts <= 0) return '-'
try {
return new Date(ts * 1000).toLocaleTimeString('zh-CN', { hour12: false, timeZone: 'Asia/Shanghai' })
} catch {
return '-'
}
}
function sourceLabel(source) {
const raw = String(source ?? '').trim()
if (!raw) return '手动'
@@ -288,6 +306,38 @@ const workerModuleItems = computed(() => [
{ label: '任务队列', value: browserPoolQueueSize.value },
])
const requestTopPaths = computed(() => {
const rows = requestMetrics.value?.top_paths
if (!Array.isArray(rows)) return []
return rows.slice(0, 3)
})
const requestModuleItems = computed(() => {
const items = [
{ label: '总请求', value: normalizeCount(requestMetrics.value?.total_requests) },
{ label: 'API请求', value: normalizeCount(requestMetrics.value?.api_requests) },
{ label: '慢请求', value: normalizeCount(requestMetrics.value?.slow_requests) },
{ label: '错误请求', value: normalizeCount(requestMetrics.value?.error_requests) },
]
requestTopPaths.value.forEach((row, index) => {
const pathText = String(row?.path || '-')
items.push({
label: `慢接口${index + 1}`,
value: `${pathText} · 峰值 ${formatMs(row?.max_ms)}`,
})
})
return items
})
const requestModuleDesc = computed(() => {
const avgMs = formatMs(requestMetrics.value?.avg_duration_ms)
const maxMs = formatMs(requestMetrics.value?.max_duration_ms)
const lastAt = formatUnixTime(requestMetrics.value?.last_request_ts)
return `均值 ${avgMs} · 峰值 ${maxMs} · 最近 ${lastAt}`
})
const configModuleItems = computed(() => [
{ label: '定时任务', value: scheduleEnabled.value ? '启用' : '关闭' },
{ label: '执行时间', value: scheduleTime.value || '-' },
@@ -342,6 +392,13 @@ const mobileModules = computed(() => [
tone: 'green',
items: resourceModuleItems.value,
},
{
key: 'request',
title: '接口性能',
desc: requestModuleDesc.value,
tone: 'purple',
items: requestModuleItems.value,
},
{
key: 'worker',
title: '截图线程池',
@@ -374,6 +431,7 @@ async function refreshAll(options = {}) {
serverResult,
dockerResult,
browserPoolResult,
requestMetricsResult,
configResult,
] = await Promise.allSettled([
fetchTaskStats(),
@@ -383,6 +441,7 @@ async function refreshAll(options = {}) {
fetchServerInfo(),
fetchDockerStats(),
fetchBrowserPoolStats(),
fetchRequestMetrics(),
fetchSystemConfig(),
])
@@ -393,6 +452,7 @@ async function refreshAll(options = {}) {
if (serverResult.status === 'fulfilled') serverInfo.value = serverResult.value
if (dockerResult.status === 'fulfilled') dockerStats.value = dockerResult.value
if (browserPoolResult.status === 'fulfilled') browserPoolStats.value = browserPoolResult.value
if (requestMetricsResult.status === 'fulfilled') requestMetrics.value = requestMetricsResult.value
if (configResult.status === 'fulfilled') systemConfig.value = configResult.value
await refreshStats?.()