; label: string; key: string;
{ group: 'tcp-connect', label: 'TCP RTT p50', key: 'tcp.rtt.p50', fmt: fmtMs },
{ group: 'tcp-connect', label: 'TCP RTT p99', key: 'tcp.rtt.p99', fmt: fmtMs },
{ group: 'tcp-connect', label: 'TCP RTT 最大', key: 'tcp.rtt.max', fmt: fmtMs },
- { group: 'tcp-connect', label: 'TCP 重传率', key: 'tcp.retrans', fmt: fmtPct, good: 0.5, poor: 3 },
+ { group: 'tcp-connect', label: 'TCP 去程重传率', key: 'tcp.retrans.up', fmt: fmtPct, good: 0.5, poor: 3 },
+ { group: 'tcp-connect', label: 'TCP 回程重传率', key: 'tcp.retrans.down', fmt: fmtPct, good: 0.5, poor: 3 },
{ group: 'tcp-connect', label: 'TCP 建连 p95', key: 'connect.tcp_ms.p95', fmt: fmtMs, optional: true },
{ group: 'tcp-connect', label: 'TLS 握手 p95', key: 'connect.tls_ms.p95', fmt: fmtMs, optional: true },
{ group: 'tcp-connect', label: '建连成功率', key: 'connect.success', fmt: fmtPct, optional: true },
@@ -64,11 +65,11 @@ const GROUPS = [
const CHARTS: ChartDef[] = [
{ id: 'rtt', title: '延迟', group: 'quic', unit: 'ms', series: [{ key: 'rtt.p50', label: 'p50', color: '--chart-1' }, { key: 'rtt.p95', label: 'p95', color: '--chart-2' }, { key: 'rtt.p99', label: 'p99', color: '--chart-3' }] },
- { id: 'jitter', title: '抖动(p95)', group: 'quic', unit: 'ms', series: [{ key: 'jitter.up.p95', label: '上行', color: '--chart-2' }, { key: 'jitter.down.p95', label: '下行', color: '--chart-1' }] },
- { id: 'loss', title: '丢包', group: 'quic', unit: '%', series: [{ key: 'loss.up', label: '上行', color: '--chart-2' }, { key: 'loss.down', label: '下行', color: '--chart-3' }, { key: 'loss.total', label: '合计', color: '--chart-1', dash: [4, 3] }] },
- { id: 'loss-runs', title: '最长连续丢包', group: 'quic', unit: '包', series: [{ key: 'loss.run.up_max', label: '上行', color: '--chart-2' }, { key: 'loss.run.down_max', label: '下行', color: '--chart-3' }] },
+ { id: 'jitter', title: '抖动(p95)', group: 'quic', unit: 'ms', series: [{ key: 'jitter.up.p95', label: '去程', color: '--chart-2' }, { key: 'jitter.down.p95', label: '回程', color: '--chart-1' }] },
+ { id: 'loss', title: '丢包', group: 'quic', unit: '%', series: [{ key: 'loss.up', label: '去程', color: '--chart-2' }, { key: 'loss.down', label: '回程', color: '--chart-3' }, { key: 'loss.total', label: '合计', color: '--chart-1', dash: [4, 3] }] },
+ { id: 'loss-runs', title: '最长连续丢包', group: 'quic', unit: '包', series: [{ key: 'loss.run.up_max', label: '去程', color: '--chart-2' }, { key: 'loss.run.down_max', label: '回程', color: '--chart-3' }] },
{ id: 'tcp', title: '往返时延(RTT)', group: 'tcp-connect', unit: 'ms', series: [{ key: 'tcp.rtt.p50', label: 'p50', color: '--chart-1' }, { key: 'tcp.rtt.p95', label: 'p95', color: '--chart-2' }, { key: 'tcp.rtt.max', label: '最大', color: '--chart-3' }] },
- { id: 'retrans', title: '重传率', group: 'tcp-connect', unit: '%', fill: true, series: [{ key: 'tcp.retrans', label: '重传率', color: '--chart-3' }] },
+ { id: 'retrans', title: '重传率', group: 'tcp-connect', unit: '%', series: [{ key: 'tcp.retrans.up', label: '去程', color: '--chart-2' }, { key: 'tcp.retrans.down', label: '回程', color: '--chart-3' }, { key: 'tcp.retrans', label: '合计', color: '--chart-1', dash: [4, 3] }] },
{ id: 'connect-time', title: '建连耗时(p95)', group: 'tcp-connect', unit: 'ms', series: [{ key: 'connect.tcp_ms.p95', label: 'TCP 建连', color: '--chart-1' }, { key: 'connect.tls_ms.p95', label: 'TLS 握手', color: '--chart-2' }] },
{ id: 'connect-ok', title: '建连成功率', group: 'tcp-connect', unit: '%', zero: false, series: [{ key: 'connect.success', label: '成功率', color: '--chart-3' }] },
{ id: 'score', title: '综合评分', group: 'score', wide: true, unit: '', series: [{ key: 'score.reality', label: 'REALITY', color: '--chart-1' }, { key: 'score.hy2', label: 'Hy2', color: '--chart-2' }, { key: 'score.mc', label: 'MC', color: '--chart-4' }, { key: 'score.base', label: '综合', color: '--chart-5', dash: [4, 3] }] },
@@ -316,7 +317,7 @@ export function Line() {
QUIC Datagram 丢包
总丢包{fmtPct(m['loss.total'])}
-
↑ {fmtPct(m['loss.up'])}/↓ {fmtPct(m['loss.down'])}
+
去 {fmtPct(m['loss.up'])}/回 {fmtPct(m['loss.down'])}
最长连续 ↑ {fmtNum(m['loss.run.up_max'])} / ↓ {fmtNum(m['loss.run.down_max'])} 包
diff --git a/web/display/src/pages/Overview.tsx b/web/display/src/pages/Overview.tsx
index 3299065..1f4463c 100644
--- a/web/display/src/pages/Overview.tsx
+++ b/web/display/src/pages/Overview.tsx
@@ -12,7 +12,7 @@ import { PageError } from '../lib'
import { IPV6_STATES, IpVersionPicker, ipVersionOf } from '@shared/ipVersions'
import { LineStrips, OVERVIEW_RANGES, type OverviewRange } from '../LineStrips'
-const METRICS = ['rtt.p50', 'rtt.p95', 'rtt.p99', 'loss.total', 'loss.up', 'loss.down', 'tcp.rtt.p50', 'tcp.retrans'].join(',')
+const METRICS = ['rtt.p50', 'rtt.p95', 'rtt.p99', 'loss.total', 'loss.up', 'loss.down', 'tcp.rtt.p50', 'tcp.retrans', 'tcp.retrans.up', 'tcp.retrans.down'].join(',')
type SortKey = 'name' | 'rtt' | 'loss'
@@ -136,7 +136,7 @@ function NodeCard({ node, labels, infos }: { node: HostItem; labels: string[]; i
)
}
-/** 一条线路(拨号方 → 监听方):近一段时间的 QUIC Datagram 上下行丢包、RTT 和 TCP 重传。 */
+/** 一条线路(拨号方 ⇄ 监听方):RTT 是往返;去程是拨号方到监听方(左到右),回程是监听方到拨号方(右到左)。QUIC 看两个方向的丢包,TCP 看两个方向的重传。 */
function LineCard({ l, range, infos }: { l: OverviewLineDto; range: OverviewRange; infos: Map }) {
const dialerInfo = infos.get(l.dialer_id)
const agentInfo = infos.get(l.agent_id)
@@ -159,7 +159,7 @@ function LineCard({ l, range, infos }: { l: OverviewLineDto; range: OverviewRang
{dialerInfo?.country ? : null}
{l.dialer_name}
{dialerInfo?.isp_key ? : null}
- →
+ ⇄
{agentInfo?.country ? : null}
{l.name}