From 262f6205a1ac550431c62c0c27f7f751fc83422b Mon Sep 17 00:00:00 2001
From: githubflyideas <36397539+githubflyideas@users.noreply.github.com>
Date: Thu, 29 Oct 2026 10:28:39 +0900
Subject: [PATCH] =?UTF-8?q?Console:=20=E5=90=8C=E6=97=B6=E6=9C=9F=E5=AF=B9?=
=?UTF-8?q?=E6=AF=94=E8=99=9A=E7=BA=BF=20(previous=20period=20/=20yesterda?=
=?UTF-8?q?y=20/=20last=20week=20P50=20overlay)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Compare select next to TIME/DIV. Fetches the same target's earlier window via
/api/series from/to, shifts it onto the current window and draws the median as
a dashed line; tooltip shows the compare value and delta %. Modes that would
need data older than retention are disabled (with a reason) and fall back to
Off. Compare fetch is abortable, stale-discarded, and never breaks the main
chart; an empty comparison period is noted in the legend. No backend change.
---
i18n/strings.json | 96 ++++++++++++++++++++++++
static/index.html | 182 +++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 267 insertions(+), 11 deletions(-)
diff --git a/i18n/strings.json b/i18n/strings.json
index adf0913..0cab5ca 100644
--- a/i18n/strings.json
+++ b/i18n/strings.json
@@ -1080,6 +1080,102 @@
"ja": "線 = 1時間ごとの中央値 · 煙 = 1時間ごとの min/p50/p90/p99/max · 赤柱 = 損失率 · ◆ = バースト",
"ko": "선 = 시간별 중앙값 · 연기 = 시간별 min/p50/p90/p99/max · 빨간 막대 = 손실률 · ◆ = 버스트"
},
+ "console.compare": {
+ "en": "COMPARE",
+ "zh": "对比",
+ "es": "COMPARAR",
+ "fr": "COMPARER",
+ "pt": "COMPARAR",
+ "ru": "СРАВНЕНИЕ",
+ "id": "BANDINGKAN",
+ "de": "VERGLEICH",
+ "ja": "比較",
+ "ko": "비교"
+ },
+ "console.cmpOff": {
+ "en": "Off",
+ "zh": "关闭",
+ "es": "Desactivado",
+ "fr": "Désactivé",
+ "pt": "Desligado",
+ "ru": "Выкл.",
+ "id": "Mati",
+ "de": "Aus",
+ "ja": "オフ",
+ "ko": "끄기"
+ },
+ "console.cmpPrev": {
+ "en": "Previous period",
+ "zh": "上一周期",
+ "es": "Período anterior",
+ "fr": "Période précédente",
+ "pt": "Período anterior",
+ "ru": "Предыдущий период",
+ "id": "Periode sebelumnya",
+ "de": "Vorheriger Zeitraum",
+ "ja": "前の期間",
+ "ko": "이전 기간"
+ },
+ "console.cmpDay": {
+ "en": "Yesterday, same time",
+ "zh": "昨天同时",
+ "es": "Ayer, misma hora",
+ "fr": "Hier, même heure",
+ "pt": "Ontem, mesmo horário",
+ "ru": "Вчера в это же время",
+ "id": "Kemarin, jam yang sama",
+ "de": "Gestern, gleiche Zeit",
+ "ja": "昨日の同時刻",
+ "ko": "어제 같은 시간"
+ },
+ "console.cmpWeek": {
+ "en": "Last week, same time",
+ "zh": "上周同时",
+ "es": "Semana pasada, misma hora",
+ "fr": "Semaine dernière, même heure",
+ "pt": "Semana passada, mesmo horário",
+ "ru": "Неделю назад в это же время",
+ "id": "Minggu lalu, jam yang sama",
+ "de": "Letzte Woche, gleiche Zeit",
+ "ja": "先週の同時刻",
+ "ko": "지난주 같은 시간"
+ },
+ "console.cmpTitle": {
+ "en": "Overlay the median of an earlier period as a dashed line. Periods older than the retention window are unavailable.",
+ "zh": "用虚线叠加更早同时期的中位数。超出保留期的时段不可选。",
+ "es": "Superpone la mediana de un período anterior como línea discontinua. Los períodos fuera de la retención no están disponibles.",
+ "fr": "Superpose la médiane d'une période antérieure en pointillés. Les périodes hors rétention ne sont pas disponibles.",
+ "pt": "Sobrepõe a mediana de um período anterior como linha tracejada. Períodos fora da retenção não estão disponíveis.",
+ "ru": "Накладывает медиану более раннего периода пунктиром. Периоды за пределами срока хранения недоступны.",
+ "id": "Menampilkan median periode sebelumnya sebagai garis putus-putus. Periode di luar masa retensi tidak tersedia.",
+ "de": "Blendet den Median eines früheren Zeitraums gestrichelt ein. Zeiträume außerhalb der Aufbewahrung sind nicht verfügbar.",
+ "ja": "以前の同じ時間帯の中央値を破線で重ねて表示します。保存期間を超える期間は選べません。",
+ "ko": "이전 기간의 중앙값을 점선으로 겹쳐 표시합니다. 보존 기간을 벗어난 기간은 선택할 수 없습니다."
+ },
+ "console.cmpBeyond": {
+ "en": "Beyond retention",
+ "zh": "超出保留期",
+ "es": "Fuera del período de retención",
+ "fr": "Hors période de rétention",
+ "pt": "Fora do período de retenção",
+ "ru": "За пределами срока хранения",
+ "id": "Di luar masa retensi",
+ "de": "Außerhalb der Aufbewahrung",
+ "ja": "保存期間外",
+ "ko": "보존 기간 초과"
+ },
+ "console.cmpNoData": {
+ "en": "no data in comparison period",
+ "zh": "对比期无数据",
+ "es": "sin datos en el período de comparación",
+ "fr": "aucune donnée sur la période de comparaison",
+ "pt": "sem dados no período de comparação",
+ "ru": "нет данных за период сравнения",
+ "id": "tidak ada data pada periode pembanding",
+ "de": "keine Daten im Vergleichszeitraum",
+ "ja": "比較期間のデータなし",
+ "ko": "비교 기간에 데이터 없음"
+ },
"console.tagline": {
"en": "One binary. One graph. One metric: Latency.",
"zh": "一个文件。一张图。一个指标:延迟。",
diff --git a/static/index.html b/static/index.html
index f924abb..952cc0c 100644
--- a/static/index.html
+++ b/static/index.html
@@ -135,6 +135,12 @@
.rng button:hover { color:var(--ink); }
.rng button.on { background:color-mix(in srgb, var(--amber) 15%, transparent);
color:var(--amber); font-weight:700; }
+ /* 同时期对比:一个下拉,和 TIME/DIV 并排,沿用同一套面板样式 */
+ .rng select { font-family:var(--sans); font-size:var(--fs-small); background:none; border:0;
+ color:var(--ink); padding:7px 10px 7px 4px; cursor:pointer; }
+ .rng select:focus { outline:none; color:var(--phos); }
+ .rng select option { background:var(--panel); color:var(--ink); }
+ .rng select option:disabled { color:var(--dim); }
.scope { background:var(--panel); border:1px solid var(--line); border-radius:6px; padding:14px; }
.crt { position:relative; }
#chart { height:420px; background:var(--screen); border-radius:4px; }
@@ -295,6 +301,15 @@
+