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

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 489b18962 fix(metrics): keep CSV epochs in one unit (#5726)
489b18962 is described below

commit 489b189628b248b80b09e568083d38090de9304f
Author: 0 <[email protected]>
AuthorDate: Mon Oct 19 18:13:56 2026 +0800

    fix(metrics): keep CSV epochs in one unit (#5726)
    
    Verified against `rocketmq-studio` at 86aa49c34 before merging: 缺陷仍在。文件已从 
`web/src/pages/metrics/MetricsExplorer.tsx` 迁到 
`web/src/components/MetricsExplorer.tsx`,但链路一模一样:`:612` `const queriedAt = 
Date.now()`(毫秒)、`:
    
    merge-tree clean against the current trunk and no outstanding must-fix 
items; merged as-is (squash) per the maintainer review of 2026-10-19.
---
 web/src/utils/metricsExplorerDiagnostics.test.ts | 18 ++++++++++++++++++
 web/src/utils/metricsExplorerDiagnostics.ts      | 13 ++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/web/src/utils/metricsExplorerDiagnostics.test.ts 
b/web/src/utils/metricsExplorerDiagnostics.test.ts
index ca12f237c..09362bc99 100644
--- a/web/src/utils/metricsExplorerDiagnostics.test.ts
+++ b/web/src/utils/metricsExplorerDiagnostics.test.ts
@@ -322,6 +322,24 @@ describe('metrics explorer diagnostics', () => {
     expect(csv).toContain('"2027-01-15T07:00:00.000Z"');
   });
 
+  it('keeps every epoch column of a CSV row in the same time unit', () => {
+    const rows = buildMetricCsvRows(metricData, metric, {
+      profileName: 'RocketMQ 5.x Native',
+      sourceName: 'Prometheus prod',
+      queryStart: 1_799_996_400,
+      queryEnd: 1_800_000_000,
+      queriedAt: 1_800_000_000_000,
+    });
+
+    // Timestamp / Query Start / Query End are epoch seconds; Queried At 
arrives from the
+    // caller as epoch milliseconds, but one CSV file must not mix the two 
units.
+    for (const row of rows) {
+      expect(row.queriedAt).toBe(1_800_000_000);
+      expect(row.queryStart).toBe(1_799_996_400);
+      expect(row.queryEnd).toBe(1_800_000_000);
+    }
+  });
+
   it('creates deterministic CSV filenames from metric identity', () => {
     expect(buildMetricCsvFilename(metric, 1_800_000_000_000)).toBe(
       'rocketmq-studio-metrics-message-in-tps-2027-01-15T08-00-00-000Z.csv',
diff --git a/web/src/utils/metricsExplorerDiagnostics.ts 
b/web/src/utils/metricsExplorerDiagnostics.ts
index c3bfcd741..4c1e89128 100644
--- a/web/src/utils/metricsExplorerDiagnostics.ts
+++ b/web/src/utils/metricsExplorerDiagnostics.ts
@@ -52,8 +52,11 @@ export interface MetricResultSummary {
 export interface MetricCsvContext {
   profileName: string;
   sourceName: string;
+  /** Epoch seconds of the query window start. */
   queryStart?: number;
+  /** Epoch seconds of the query window end. */
   queryEnd?: number;
+  /** Wall-clock `Date.now()` of the query, in epoch milliseconds. */
   queriedAt?: number;
 }
 
@@ -74,8 +77,11 @@ export interface MetricCsvRow {
   value: number;
   histogramCount?: number;
   histogramSum?: number;
+  /** Epoch seconds, like every other epoch column in the row. */
   queryStart?: number;
+  /** Epoch seconds, like every other epoch column in the row. */
   queryEnd?: number;
+  /** Epoch seconds, like every other epoch column in the row. */
   queriedAt?: number;
 }
 
@@ -258,6 +264,11 @@ export const buildMetricCsvRows = (
     const { samples } = toMetricSeriesSamples(series);
     const seriesLabel = metricSeriesLabel(series, metric.name);
     const labels = stableLabelsText(series.labels);
+    // Timestamp / Query Start / Query End are epoch seconds; `queriedAt` is a 
wall-clock
+    // `Date.now()` in milliseconds. One CSV file must not mix the two units, 
so the query
+    // instant is emitted in the same seconds unit as the rest of the epoch 
columns.
+    const queriedAtSeconds =
+      context.queriedAt === undefined ? undefined : 
Math.floor(context.queriedAt / 1000);
     return samples.map((sample) => ({
       profileName: context.profileName,
       sourceName: context.sourceName,
@@ -277,7 +288,7 @@ export const buildMetricCsvRows = (
       histogramSum: sample.histogramSum,
       queryStart: context.queryStart,
       queryEnd: context.queryEnd,
-      queriedAt: context.queriedAt,
+      queriedAt: queriedAtSeconds,
     }));
   });
 

Reply via email to