AsyncLocalStorage Correlation Logging
Tag every log line with a request correlation id using AsyncLocalStorage, letting deeply nested async code log without passing context.
Code
import { AsyncLocalStorage } from 'node:async_hooks';
import pino from 'pino';
interface RequestScope {
requestId: string;
userId?: string;
}
const storage = new AsyncLocalStorage<RequestScope>();
const logger = pino({
level: 'info',
mixin: () => {
const scope = storage.getStore();
return scope ? { requestId: scope.requestId, userId: scope.userId } : {};
},
});
async function chargeCard(orderId: string) {
logger.info({ orderId }, 'charging card'); // 自动带上请求上下文
await new Promise((r) => setTimeout(r, 10));
}
async function handleCheckout(req) {
await chargeCard('ord-5');
await refundIfDuplicate('ord-5');
}
async function refundIfDuplicate(orderId: string) {
logger.warn({ orderId }, 'duplicate detected');
}
async function entry(request) {
const scope: RequestScope = {
requestId: request.headers['x-request-id'] ?? crypto.randomUUID(),
userId: request.headers['x-user-id'],
};
// 后续整条异步链路都在同一 scope 内执行
return storage.run(scope, () => handleCheckout(request));
}
await entry({ headers: {} });Report a problem with this exampleOpens a pre-filled issue on GitHub.