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 bc33d7098 fix(message): map trace node statuses on the key lookup too
(#4746)
bc33d7098 is described below
commit bc33d709877b8bc62b2d2869eb1f00157cf15c1f
Author: 烤化の初雪 <[email protected]>
AuthorDate: Thu Sep 24 17:46:12 2026 +0800
fix(message): map trace node statuses on the key lookup too (#4746)
test(message): pin the key lookup null and node-default contracts
The fix leaves the response normalisation on the key lookup, so the two
branches it introduces need their own coverage: a trace the server
answers with a null payload stays null (the "no trace found" contract the
key lookup already had), and a trace without a nodes array yields an
empty node list instead of leaking the missing field to the Steps
component.
fix(message): map trace node statuses on the key lookup too
GET /messages/trace-by-key returns the same broker node statuses as
GET /messages/{msgId}/trace ("finish" | "failed" | ...), but only the
msgId wrapper normalised them through mapTraceNodeStatus. A failed node
reached through the key lookup therefore kept its raw "failed" status,
which Ant Design Steps cannot render and which the trace diagnostics
panel does not recognise as a failure, so a broken trace was reported as
healthy.
Map the nodes in getMessageTraceByKey the same way, keeping the existing
null (no trace found) contract.
---
web/src/api/message.test.ts | 53 +++++++++++++++++++++++++++++++++++++++++++++
web/src/api/message.ts | 14 ++++++++++--
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/web/src/api/message.test.ts b/web/src/api/message.test.ts
index 33a06d263..a190fbc0e 100644
--- a/web/src/api/message.test.ts
+++ b/web/src/api/message.test.ts
@@ -21,6 +21,7 @@ import client from './client';
import {
consumeMessageDirectly,
getMessageTrace,
+ getMessageTraceByKey,
queryMessagePage,
queryMessages,
} from './message';
@@ -173,6 +174,58 @@ describe('message API', () => {
expect(mapped.consumerStatus).toEqual([]);
});
+ it('maps backend trace node statuses on the key lookup too', async () => {
+ const trace = {
+ nodes: [
+ {
+ title: 'Produce',
+ timestamp: 1784246400000,
+ status: 'failed',
+ costTime: 1,
+ description: 'x',
+ },
+ {
+ title: 'Consume',
+ timestamp: 1784246400000,
+ status: 'finish',
+ costTime: 1,
+ description: 'x',
+ },
+ {
+ title: 'Unknown',
+ timestamp: 1784246400000,
+ status: 'something-else',
+ costTime: 1,
+ description: 'x',
+ },
+ ],
+ consumerStatus: [],
+ };
+ mock
+ .onGet('/messages/trace-by-key', { params: { key: 'order-1', instanceId:
'instance-1' } })
+ .reply(200, { code: 200, data: trace });
+
+ const mapped = await getMessageTraceByKey('order-1', 'instance-1');
+ expect(mapped?.nodes.map((node) => node.status)).toEqual(['error',
'finish', 'wait']);
+ });
+
+ it('keeps the key lookup null and node-default contracts', async () => {
+ mock
+ .onGet('/messages/trace-by-key', { params: { key: 'missing', instanceId:
'instance-1' } })
+ .reply(200, { code: 200, data: null });
+
+ await expect(getMessageTraceByKey('missing',
'instance-1')).resolves.toBeNull();
+
+ mock
+ .onGet('/messages/trace-by-key', { params: { key: 'no-nodes',
instanceId: 'instance-1' } })
+ .reply(200, { code: 200, data: { consumerStatus: [] } });
+
+ await expect(getMessageTraceByKey('no-nodes',
'instance-1')).resolves.toEqual({
+ consumerStatus: [],
+ nodes: [],
+ });
+ });
+
it('encodes message IDs before requesting trace records', async () => {
const trace = {
nodes: [],
diff --git a/web/src/api/message.ts b/web/src/api/message.ts
index bb31baabf..7d9ee46c9 100644
--- a/web/src/api/message.ts
+++ b/web/src/api/message.ts
@@ -209,8 +209,18 @@ export async function getMessageTraceByKey(
if (instanceId !== undefined) params.instanceId = instanceId;
if (topic !== undefined) params.topic = topic;
if (traceTopic !== undefined && traceTopic.trim()) params.traceTopic =
traceTopic.trim();
- const res = await client.get<{ data: TraceRecord
}>('/messages/trace-by-key', { params });
- return res.data.data;
+ const res = await client.get<{ data: TraceRecord | null
}>('/messages/trace-by-key', { params });
+ const trace = res.data.data;
+ if (!trace) {
+ return null;
+ }
+ return {
+ ...trace,
+ nodes: (trace.nodes ?? []).map((node) => ({
+ ...node,
+ status: mapTraceNodeStatus(node.status),
+ })),
+ };
}
// ─── DLQ ────────────────────────────────────────────────────────