refactor(web): 精简诊断页即时指标

This commit is contained in:
chuan
2026-08-10 15:56:29 +08:00
parent c70d7e5c7b
commit d0e51bed4e
2 changed files with 8 additions and 23 deletions
+1
View File
@@ -346,6 +346,7 @@
- [x] 将 HTTP 请求并发客户端错误服务端错误和延迟分布写入诊断历史
- [x] 增加配置查询完整校验原子保存并发修订和统一重启提示
- [x] 增加 Web 诊断页和配置管理页
- [x] 精简诊断页即时指标并由趋势图承担重复的资源和吞吐数据
- [x] 使用页签拆分配置分类并隐藏底层配置存储位置
- [x] 将主配置和内容过滤规则合并为唯一 `config.toml`
- [ ] 将用户可编辑配置的持久化适配器从 TOML 迁移到 SQLite
+7 -23
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { AlertTriangle, Cpu, Database, Gauge, HardDrive, LoaderCircle, MemoryStick, Network } from '@lucide/vue'
import { AlertTriangle, Database, Gauge, HardDrive, LoaderCircle, Network } from '@lucide/vue'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts'
@@ -171,37 +171,21 @@ onBeforeUnmount(() => {
<div v-if="loading && !sample" class="flex min-h-72 items-center justify-center text-sm text-muted-foreground"><LoaderCircle class="mr-2 size-5 animate-spin" />正在读取诊断数据</div>
<template v-else-if="sample">
<section v-if="stats">
<h2 class="mb-3 text-sm font-semibold">服务运行状态</h2>
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
<article class="diagnostic-card"><HardDrive /><span>磁盘状态</span><b class="flex items-center gap-2"><i class="size-1.5 rounded-full" :class="stats.disk_state === 'normal' ? 'bg-emerald-500' : 'bg-amber-500'" />{{ diskStateLabel(stats.disk_state) }}</b></article>
<article class="diagnostic-card"><HardDrive /><span>磁盘剩余</span><b>{{ stats.disk_available_bytes === null ? '未知' : formatBytes(stats.disk_available_bytes) }}</b></article>
<h2 class="mb-3 text-sm font-semibold">服务概览</h2>
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
<article class="diagnostic-card"><HardDrive /><span>磁盘</span><b class="flex items-center gap-2"><i class="size-1.5 rounded-full" :class="stats.disk_state === 'normal' ? 'bg-emerald-500' : 'bg-amber-500'" />{{ diskStateLabel(stats.disk_state) }}<small class="font-normal text-muted-foreground">{{ stats.disk_available_bytes === null ? '剩余未知' : `剩余 ${formatBytes(stats.disk_available_bytes)}` }}</small></b></article>
<article class="diagnostic-card"><Network /><span>DHT 节点</span><b>{{ stats.nodes.toLocaleString() }}</b></article>
<article class="diagnostic-card"><Gauge /><span>Metadata 成功</span><b>{{ stats.metadata_ok.toLocaleString() }}</b></article>
<article class="diagnostic-card"><Gauge /><span>Metadata 下载中</span><b>{{ stats.metadata_in_flight.toLocaleString() }}</b></article>
<article class="diagnostic-card"><Database /><span>新收录</span><b>{{ stats.persistence_inserted.toLocaleString() }}</b></article>
<article class="diagnostic-card"><Database /><span>已过滤</span><b>{{ stats.metadata_filtered.toLocaleString() }}</b></article>
<article class="diagnostic-card"><Database /><span>本次新收录</span><b>{{ stats.persistence_inserted.toLocaleString() }}</b></article>
<article class="diagnostic-card"><Database /><span>已索引内容</span><b>{{ stats.indexed_documents.toLocaleString() }}</b></article>
<article class="diagnostic-card"><Gauge /><span>验证成功</span><b>{{ stats.verification_succeeded.toLocaleString() }}</b></article>
</div>
</section>
<section class="mt-6">
<h2 class="mb-3 text-sm font-semibold">资源状态</h2>
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
<article class="diagnostic-card"><MemoryStick /><span>私有内存</span><b>{{ sample.process.private_memory_bytes === null ? '未知' : formatBytes(sample.process.private_memory_bytes) }}</b></article>
<article class="diagnostic-card"><Cpu /><span>CPU 时间</span><b>{{ sample.process.cpu_time_millis === null ? '未知' : `${(sample.process.cpu_time_millis / 1000).toFixed(1)}` }}</b></article>
<article class="diagnostic-card"><Database /><span>RocksDB 缓存</span><b>{{ sample.storage.block_cache_bytes === null ? '未知' : formatBytes(sample.storage.block_cache_bytes) }}</b></article>
<article class="diagnostic-card"><HardDrive /><span> Compaction</span><b>{{ sample.storage.pending_compaction_bytes === null ? '未知' : formatBytes(sample.storage.pending_compaction_bytes) }}</b></article>
<article class="diagnostic-card"><Network /><span>HTTP 并发</span><b>{{ sample.http.active_requests }}</b></article>
<article class="diagnostic-card"><Gauge /><span>HTTP P95</span><b>{{ sample.http.latency_p95_millis === null ? '暂无' : `${sample.http.latency_p95_millis} ms` }}</b></article>
</div>
</section>
<section class="mt-5 grid gap-4 lg:grid-cols-2">
<section class="mt-6 grid gap-4 lg:grid-cols-2">
<article class="chart-card"><div><h2>进程内存</h2><p>{{ sample.process.thread_count ?? '未知' }} 个线程 · {{ sample.process.handle_count ?? '未知' }} 个句柄</p></div><VChart class="diagnostic-chart" :option="memoryChart" autoresize /></article>
<article class="chart-card"><div><h2>RocksDB 内存与压缩</h2><p>SST {{ sample.storage.live_sst_bytes === null ? '未知' : formatBytes(sample.storage.live_sst_bytes) }}</p></div><VChart class="diagnostic-chart" :option="storageChart" autoresize /></article>
<article class="chart-card lg:col-span-2"><div><h2>网络与 Metadata 吞吐</h2><p>{{ history?.samples.length ?? 0 }} 个采样点 · 最近保存 {{ formatDate(current?.status.last_persisted_at ?? null) }}</p></div><VChart class="diagnostic-chart" :option="throughputChart" autoresize /></article>
<article class="chart-card lg:col-span-2"><div><h2>HTTP 请求与错误</h2><p>累计 {{ sample.http.requests.toLocaleString() }} 个请求 · {{ sample.http.server_errors.toLocaleString() }} 个服务端错误</p></div><VChart class="diagnostic-chart" :option="httpChart" autoresize /></article>
<article class="chart-card lg:col-span-2"><div><h2>HTTP 请求与错误</h2><p>当前并发 {{ sample.http.active_requests }} · P95 {{ sample.http.latency_p95_millis === null ? '暂无' : `${sample.http.latency_p95_millis} ms` }}</p></div><VChart class="diagnostic-chart" :option="httpChart" autoresize /></article>
</section>
</template>
</main>