feat(report): add slow API ranking module for admin
This commit is contained in:
@@ -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?.()
|
||||
|
||||
Reference in New Issue
Block a user