feat: normalize cloud api error diagnostics

This commit is contained in:
lyon
2026-06-20 15:08:33 +08:00
parent 199ee18b58
commit b139ffd8e4
8 changed files with 223 additions and 8 deletions
+36 -1
View File
@@ -51,7 +51,7 @@ export function healthPayload({ serviceId, role, details = {} }) {
}
export function sendJson(response, statusCode, body) {
const payload = JSON.stringify(body, null, 2);
const payload = JSON.stringify(withDevErrorDiagnostic(body, statusCode), null, 2);
response.writeHead(statusCode, {
"content-type": "application/json; charset=utf-8",
"content-length": Buffer.byteLength(payload)
@@ -59,6 +59,41 @@ export function sendJson(response, statusCode, body) {
response.end(payload);
}
function withDevErrorDiagnostic(body, statusCode) {
if (!body || typeof body !== "object" || Array.isArray(body) || statusCode < 400 || !("error" in body)) return body;
const error = typeof body.error === "object" && body.error !== null && !Array.isArray(body.error)
? { ...body.error }
: { code: String(body.error || "unknown_error"), message: String(body.message || body.error || "unknown_error") };
const businessTraceId = typeof error.traceId === "string" && /^trc_[A-Za-z0-9_.:-]+$/u.test(error.traceId)
? error.traceId
: typeof body.traceId === "string" && /^trc_[A-Za-z0-9_.:-]+$/u.test(body.traceId)
? body.traceId
: null;
return {
...body,
error: {
...error,
userMessage: error.userMessage || error.message || body.message || error.code,
diagnostic: {
contractVersion: "hwlab-error-diagnostic-v1",
traceId: /^[0-9a-f]{32}$/u.test(String(error.traceId ?? body.traceId ?? "")) ? String(error.traceId ?? body.traceId).toLowerCase() : null,
businessTraceId,
requestId: null,
serviceId: body.serviceId || error.serviceId || "hwlab-dev-entrypoint",
route: String(error.route || body.path || "/").split("?")[0].slice(0, 180),
layer: error.layer || "dev-entrypoint",
category: error.category || (statusCode >= 500 ? "server" : "client"),
code: error.code || String(body.error || "unknown_error"),
httpStatus: statusCode,
source: "dev-entrypoint",
observedAt: new Date().toISOString(),
valuesPrinted: false
},
valuesPrinted: error.valuesPrinted === true ? true : false
}
};
}
export function createServiceServer({ serviceId, role, routes = new Map(), details = () => ({}) }) {
return createServer(async (request, response) => {
try {