feat(grid): show query elapsed time in adaptive units

This commit is contained in:
Abeautifulsnow authored and GitHub committed 2026-09-24 19:33:19 +08:00
1 parent a6f841293b
commit 900f99797f
21 files changed
+195 -69

No files matched your search

+44
View File
@@ -0,0 +1,44 @@
import { describe, expect, it } from "vitest";
import { formatDurationUs, formatQueryDuration } from "../duration";
describe("formatQueryDuration", () => {
it("clamps non-finite and negative inputs", () => {
expect(formatQueryDuration(Number.NaN)).toBe("0 ms");
expect(formatQueryDuration(-1)).toBe("0 ms");
});
it("keeps sub-second durations in integer milliseconds", () => {
expect(formatQueryDuration(0)).toBe("0 ms");
expect(formatQueryDuration(999)).toBe("999 ms");
});
it("shows one decimal second between 1s and 60s (floor-truncated)", () => {
expect(formatQueryDuration(1_000)).toBe("1.0 s");
expect(formatQueryDuration(1_234)).toBe("1.2 s");
expect(formatQueryDuration(59_999)).toBe("59.9 s");
});
it("shows minutes + seconds between 1min and 1h", () => {
expect(formatQueryDuration(60_000)).toBe("1m 0s");
expect(formatQueryDuration(65_000)).toBe("1m 5s");
expect(formatQueryDuration(3_599_999)).toBe("59m 59s");
});
it("shows hours + minutes + seconds from 1h on", () => {
expect(formatQueryDuration(3_600_000)).toBe("1h 0m 0s");
expect(formatQueryDuration(3_661_000)).toBe("1h 1m 1s");
});
});
describe("formatDurationUs", () => {
it("keeps sub-millisecond values in microseconds", () => {
expect(formatDurationUs(0)).toBe("0 µs");
expect(formatDurationUs(999)).toBe("999 µs");
});
it("converts to the ms tiers from 1ms on", () => {
expect(formatDurationUs(1_000)).toBe("1 ms");
expect(formatDurationUs(1_999)).toBe("2 ms");
expect(formatDurationUs(1_500_000)).toBe("1.5 s");
});
});
+36
View File
@@ -0,0 +1,36 @@
/**
* Adaptive, glance-friendly duration formatting for query/UI elapsed hints
* (issue #10117: raw millisecond readouts like "5230ms" scale poorly).
*
* Tiers (identical to the former `formatDataTransferDuration` in
* useExportTracker, now shared):
* < 1s -> "N ms" (integer milliseconds)
* < 60s -> "X.X s" (one decimal, floor-truncated)
* < 1h -> "Nm Ss"
* >= 1h -> "Hh MMm Ss"
*/
export function formatQueryDuration(elapsedMs: number): string {
const safeElapsedMs = Math.max(0, Number.isFinite(elapsedMs) ? Math.round(elapsedMs) : 0);
if (safeElapsedMs < 1000) return `${safeElapsedMs} ms`;
if (safeElapsedMs < 60_000) return `${(Math.floor(safeElapsedMs / 100) / 10).toFixed(1)} s`;
const totalSeconds = Math.floor(safeElapsedMs / 1000);
const seconds = totalSeconds % 60;
const totalMinutes = Math.floor(totalSeconds / 60);
if (totalMinutes < 60) return `${totalMinutes}m ${seconds}s`;
const hours = Math.floor(totalMinutes / 60);
return `${hours}h ${totalMinutes % 60}m ${seconds}s`;
}
/**
* Server-side execution times reported in microseconds (OceanBase SQL Audit
* EXECUTE_TIME): keep µs below one millisecond, then reuse the ms tiers.
*/
export function formatDurationUs(micros: number): string {
const safeMicros = Math.max(0, Number.isFinite(micros) ? Math.round(micros) : 0);
if (safeMicros < 1000) return `${safeMicros} µs`;
return formatQueryDuration(safeMicros / 1000);
}