diff --git a/vehicle-data-platform/apps/web/src/api/client.test.ts b/vehicle-data-platform/apps/web/src/api/client.test.ts index ea7141a2..f6f59847 100644 --- a/vehicle-data-platform/apps/web/src/api/client.test.ts +++ b/vehicle-data-platform/apps/web/src/api/client.test.ts @@ -38,7 +38,7 @@ test('rawFramesQuery posts structured JSON instead of URL query strings', async }); }); -test('api errors include backend message and detail', async () => { +test('api errors include backend message, detail, and trace id', async () => { vi.spyOn(globalThis, 'fetch').mockResolvedValue({ ok: false, status: 500, @@ -53,5 +53,5 @@ test('api errors include backend message and detail', async () => { }) } as Response); - await expect(api.opsHealth()).rejects.toThrow('服务处理失败: TDengine timeout'); + await expect(api.opsHealth()).rejects.toThrow('服务处理失败: TDengine timeout (traceId: trace-error)'); }); diff --git a/vehicle-data-platform/apps/web/src/api/client.ts b/vehicle-data-platform/apps/web/src/api/client.ts index 867cd797..0bd9b80d 100644 --- a/vehicle-data-platform/apps/web/src/api/client.ts +++ b/vehicle-data-platform/apps/web/src/api/client.ts @@ -34,6 +34,7 @@ type ApiErrorEnvelope = { message?: string; detail?: string; }; + traceId?: string; }; async function request(path: string, init?: RequestInit): Promise { @@ -50,11 +51,12 @@ async function responseErrorMessage(response: Response) { const envelope = (await response.json()) as ApiErrorEnvelope; const message = envelope.error?.message?.trim(); const detail = envelope.error?.detail?.trim(); + const traceID = envelope.traceId?.trim(); if (message && detail) { - return `${message}: ${detail}`; + return withTraceID(`${message}: ${detail}`, traceID); } if (message) { - return message; + return withTraceID(message, traceID); } } catch { // Fall back to status when the server does not return the platform envelope. @@ -62,6 +64,10 @@ async function responseErrorMessage(response: Response) { return `request failed ${response.status}`; } +function withTraceID(message: string, traceID?: string) { + return traceID ? `${message} (traceId: ${traceID})` : message; +} + export const api = { dashboardSummary: () => request('/api/dashboard/summary'), vehicles: (params = new URLSearchParams()) => request>(`/api/vehicles?${params.toString()}`),