feat(api): assign and echo request ids

This commit is contained in:
2026-04-21 13:32:50 +00:00
parent fe4fdb32d7
commit 9d925f9401
2 changed files with 19 additions and 1 deletions
+3
View File
@@ -64,6 +64,7 @@ Deno.test('ApiServer serves health metrics and authenticated model listings', as
assertEquals(healthResponse.status, 200);
assertEquals(healthBody.status, 'ok');
assertEquals(healthBody.models, 1);
assertEquals(typeof healthResponse.headers.get('x-request-id'), 'string');
const metricsResponse = await fetch(`http://127.0.0.1:${port}/metrics`);
const metricsBody = await metricsResponse.text();
@@ -79,12 +80,14 @@ Deno.test('ApiServer serves health metrics and authenticated model listings', as
const authenticatedModels = await fetch(`http://127.0.0.1:${port}/v1/models`, {
headers: {
Authorization: 'Bearer valid-key',
'X-Request-Id': 'req-test-models',
},
});
const authenticatedBody = await authenticatedModels.json();
assertEquals(authenticatedModels.status, 200);
assertEquals(authenticatedBody.object, 'list');
assertEquals(authenticatedBody.data[0].id, 'meta-llama/Llama-3.1-8B-Instruct');
assertEquals(authenticatedModels.headers.get('x-request-id'), 'req-test-models');
const metricsAfterRequests = await fetch(`http://127.0.0.1:${port}/metrics`);
const metricsAfterRequestsBody = await metricsAfterRequests.text();
+16 -1
View File
@@ -123,6 +123,7 @@ export class ApiServer {
res: http.ServerResponse,
): Promise<void> {
const startTime = Date.now();
const requestId = this.ensureRequestId(req, res);
// Set CORS headers if enabled
if (this.config.cors) {
@@ -177,7 +178,7 @@ export class ApiServer {
// Log request
const duration = Date.now() - startTime;
this.recordRequest(path, res.statusCode);
logger.dim(`${req.method} ${path} - ${res.statusCode} (${duration}ms)`);
logger.dim(`[${requestId}] ${req.method} ${path} - ${res.statusCode} (${duration}ms)`);
}
/**
@@ -405,6 +406,20 @@ export class ApiServer {
metric.set(path, (metric.get(path) || 0) + 1);
}
private ensureRequestId(req: http.IncomingMessage, res: http.ServerResponse): string {
const existing = typeof req.headers['x-request-id'] === 'string'
? req.headers['x-request-id']
: undefined;
const requestId = existing || this.generateRequestId();
req.headers['x-request-id'] = requestId;
res.setHeader('X-Request-Id', requestId);
return requestId;
}
private generateRequestId(): string {
return `req-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
}
private escapeMetricLabel(value: string): string {
return value.replaceAll('\\', '\\\\').replaceAll('"', '\\"');
}