This is an automated email from the ASF dual-hosted git repository.

wu-sheng pushed a commit to branch feat/metric-trace-drilldown
in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git

commit 8cc01e7d931b41b72d01bd693b6fe402b05239b6
Author: Wu Sheng <[email protected]>
AuthorDate: Thu Jul 2 14:40:58 2026 +0800

    fix(traces): drill window snaps to the clicked hour/day bucket
    
    The window centered on a reconstructed mid-bucket point and capped the
    half-window at 6h, so clicking a DAY bucket opened a 12h mid-day slice
    (08:35–20:35) instead of that day. Now MINUTE → a ±5min neighborhood,
    HOUR → the whole clicked hour, DAY → the whole clicked day (snapped to
    the local boundary and spanning one bucket).
---
 .../render/layer-dashboard/LayerDashboardsView.vue | 33 ++++++++++++++--------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue 
b/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
index 223706d..e96d354 100644
--- a/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
+++ b/apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue
@@ -474,16 +474,28 @@ function traceDrillMode(w: DashboardWidget): 'latency' | 
'error' | null {
   return m === 'latency' || m === 'error' ? m : null;
 }
 // Half-window (ms) around the clicked bucket, scaled to step, capped at 6h.
-const DRILL_STEP_MS: Record<string, number> = { MINUTE: 60_000, HOUR: 
3_600_000, DAY: 86_400_000 };
-function drillHalfWindowMs(): number {
-  const step = DRILL_STEP_MS[timeRange.step] ?? 60_000;
-  return Math.min(Math.max(5 * 60_000, step / 2), 6 * 60 * 60_000);
-}
 function drillCenterMs(dataIndex: number, len: number): number {
   const { startMs, endMs } = timeRange.range;
   if (len <= 1) return endMs;
   return Math.round(startMs + ((endMs - startMs) * dataIndex) / (len - 1));
 }
+// Trace window for the clicked bucket. MINUTE → a ±5min neighborhood; HOUR/DAY
+// → the whole clicked hour/day (snapped to the local boundary) so the search
+// matches the bucket the operator clicked, not a mid-bucket slice. `labelMs` 
is
+// the bucket start, used for the popover's "around …" label.
+function drillWindow(dataIndex: number, len: number): { fromMs: number; toMs: 
number; labelMs: number } {
+  const center = drillCenterMs(dataIndex, len);
+  if (timeRange.step === 'MINUTE') {
+    const half = 5 * 60_000;
+    return { fromMs: center - half, toMs: center + half, labelMs: center };
+  }
+  const d = new Date(center);
+  d.setMinutes(0, 0, 0);
+  if (timeRange.step === 'DAY') d.setHours(0);
+  const fromMs = d.getTime();
+  const spanMs = timeRange.step === 'DAY' ? 86_400_000 : 3_600_000;
+  return { fromMs, toMs: fromMs + spanMs, labelMs: fromMs };
+}
 // datetime-local wall-clock — must match the Traces tab's custom-range format.
 function toLocalInput(ms: number): string {
   const d = new Date(ms);
@@ -507,15 +519,14 @@ function onDrillPoint(
   const mode = traceDrillMode(w);
   if (!mode) return;
   const len = resultsById.value.get(w.id)?.series?.[0]?.data.length ?? 0;
-  const center = drillCenterMs(p.dataIndex, len);
-  const half = drillHalfWindowMs();
+  const win = drillWindow(p.dataIndex, len);
   const ms = Math.max(0, Math.round(p.value));
   const query: Record<string, string> = {
     dMode: mode,
-    dFrom: toLocalInput(center - half),
-    dTo: toLocalInput(center + half),
+    dFrom: toLocalInput(win.fromMs),
+    dTo: toLocalInput(win.toMs),
     // Unique per click so a drill→drill navigation on the same tab re-fires.
-    dNonce: `${center}:${p.dataIndex}:${w.id}`,
+    dNonce: `${win.fromMs}:${p.dataIndex}:${w.id}`,
   };
   if (mode === 'latency') query.dValue = String(ms);
   // service (id) seeds the fresh tab's selection; instance/endpoint go by name
@@ -531,7 +542,7 @@ function onDrillPoint(
     title: w.title,
     meta:
       band +
-      t('around {t}', { t: bucketTimeLabel(timeRange.step, center) }) +
+      t('around {t}', { t: bucketTimeLabel(timeRange.step, win.labelMs) }) +
       (mode === 'latency' ? ` · ≥ ${ms} ms` : ''),
     label: mode === 'latency' ? t('View slow traces') : t('View error traces'),
   };

Reply via email to