Request IDs
One id that follows a request across services and platforms.
What it is
Every request the API lab handles gets an id, returned as X-Request-Id, written into its log line, and included in every error body, so "it failed" becomes "request a24e… failed", which anyone can look up. The id is a W3C Trace Context trace id: if the caller sends a traceparent header (00-<trace id>-<parent span id>-<flags>), the API keeps its trace id instead of making a new one, and passes it on in calls it makes itself (its webhook deliveries). So one id ties together everything one action caused, across services, across platforms, and later across traces (Phase 2).
When to use it
- Every API: return the id, and put it in error bodies
- Accept traceparent from callers; send it on to whatever you call
- Support tickets: ask for the id, not a screenshot
1. One id, two platforms
This site sends the same 404 request to both copies of the API with one traceparent. Both answer with that trace id as their X-Request-Id, both put it in the error body, and Loki returns two lines for it: one from Vercel in Washington, D.C., one from a Worker. (Called from this site's server, which runs in Washington too, the Worker runs nearby and is fast; called from a browser far away, it runs near the browser.)
Show code · src/lib/targets.ts
// The only requests this site sends to the API lab: a fixed list, chosen by
// id. A visitor can't make the server fetch an address of their choosing.
export const PLATFORMS = {
vercel: { name: "Vercel", base: "https://api.djmiskey.com" },
workers: { name: "Cloudflare Workers", base: "https://api-cf.djmiskey.com" },
} as const;
export type PlatformId = keyof typeof PLATFORMS;
export const REQUESTS = {
health: { label: "GET /api/health", path: "/api/health", note: "No database: the fastest thing the API does." },
board: { label: "GET /api/scores?game=runner", path: "/api/scores?game=runner&limit=3", note: "One database query: the Runner leaderboard." },
missing: { label: "GET a task that doesn't exist", path: "/api/tasks/00000000-0000-4000-8000-000000000000", note: "A 404: logged as a warning, with the request id in the error body." },
} as const;
export type RequestId = keyof typeof REQUESTS;
/** A W3C traceparent with a fresh trace id: the request id the API will log. */
export function newTraceparent() {
const hex = (n: number) => [...crypto.getRandomValues(new Uint8Array(n))].map((b) => b.toString(16).padStart(2, "0")).join("");
const traceId = hex(16);
return { traceId, header: `00-${traceId}-${hex(8)}-01` };
}
export const isRequestId = (id: string): id is RequestId => id in REQUESTS;
export const isPlatform = (id: string): id is PlatformId => id in PLATFORMS;
export const isTraceId = (id: string) => /^[0-9a-f]{32}$/.test(id);
Show code · src/app/api/send/route.ts
import { isPlatform, isRequestId, newTraceparent, PLATFORMS, REQUESTS } from "@/lib/targets";
// POST {"request": "health", "platforms": ["vercel", "workers"]}: send one of
// the fixed requests to the API lab, from this server, with a traceparent we
// made up, so we know the id each copy of the API will log it under. With
// two platforms, both get the same id: one id across two platforms.
export async function POST(request: Request) {
const body = (await request.json().catch(() => null)) as { request?: string; platforms?: string[] } | null;
const which = body?.request ?? "";
const platforms = (body?.platforms ?? []).filter(isPlatform);
if (!isRequestId(which) || platforms.length === 0 || platforms.length > 2) {
return Response.json({ error: "Send a known request id and one or two platforms." }, { status: 400 });
}
const { traceId, header } = newTraceparent();
const results = await Promise.all(platforms.map(async (p) => {
const started = performance.now();
const res = await fetch(`${PLATFORMS[p].base}${REQUESTS[which].path}`, { headers: { traceparent: header }, cache: "no-store", signal: AbortSignal.timeout(15_000) });
const text = await res.text();
return { platform: p, status: res.status, ms: Math.round(performance.now() - started), requestId: res.headers.get("x-request-id"), body: text.slice(0, 600) };
}));
return Response.json({ traceId, results }, { headers: { "cache-control": "no-store" } });
}