Skip to content

Commit 6db34f8

Browse files
committed
feat: add reqId for db queries
1 parent 4b62083 commit 6db34f8

File tree

5 files changed

+52
-6
lines changed

5 files changed

+52
-6
lines changed

src/infrastructure/logging/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as process from 'process';
33
import type { LoggingConfig } from '../config/index.js';
44
import appConfig from '../config/index.js';
55
import type { FastifyRequest } from 'fastify';
6+
import { getCurrentReqId } from './reqId.context.js';
67

78
const loggerConfig = process.env['NODE_ENV'] === 'production'
89
? {}
@@ -45,13 +46,14 @@ export function getLogger(moduleName: keyof LoggingConfig): pino.Logger {
4546
*/
4647
export function getRequestLogger(moduleName: keyof LoggingConfig, request?: FastifyRequest): pino.Logger {
4748
const baseLogger = getLogger(moduleName);
48-
49-
if (request && request.id) {
49+
const reqId = getCurrentReqId() ?? request?.id;
50+
51+
if (reqId) {
5052
return baseLogger.child({
51-
reqId: request.id,
53+
reqId,
5254
});
5355
}
54-
56+
5557
return baseLogger;
5658
}
5759

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { AsyncLocalStorage } from 'node:async_hooks';
2+
3+
/**
4+
* Context for storing reqId within asynchronous operations
5+
*/
6+
interface RequestContext {
7+
reqId?: string;
8+
}
9+
10+
/**
11+
* AsyncLocalStorage for storing request context
12+
* Allows tying database logs to the corresponding request
13+
*/
14+
export const requestContextStorage = new AsyncLocalStorage<RequestContext>();
15+
16+
/**
17+
* Gets the current reqId from the execution context
18+
* @returns reqId or undefined if context is not set
19+
*/
20+
export function getCurrentReqId(): string | undefined {
21+
const context = requestContextStorage.getStore();
22+
return context?.reqId;
23+
}

src/presentation/http/http-api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { fastifyOauth2 } from '@fastify/oauth2';
99
import fastifySwagger from '@fastify/swagger';
1010
import fastifySwaggerUI from '@fastify/swagger-ui';
1111
import addUserIdResolver from '@presentation/http/middlewares/common/userIdResolver.js';
12+
import addReqIdContext from '@presentation/http/middlewares/common/reqIdContext.js';
1213
import cookie from '@fastify/cookie';
1314
import { notFound, forbidden, unauthorized, notAcceptable, domainError } from './decorators/index.js';
1415
import NoteRouter from '@presentation/http/router/note.js';
@@ -324,6 +325,7 @@ export default class HttpApi implements Api {
324325
throw new Error('Server is not initialized');
325326
}
326327

328+
addReqIdContext(this.server);
327329
addUserIdResolver(this.server, domainServices.authService);
328330
}
329331

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { FastifyInstance } from 'fastify';
2+
import { requestContextStorage } from '@infrastructure/logging/reqId.context.js';
3+
4+
/**
5+
* Adds middleware to set reqId context at the beginning of each request
6+
* @param server - fastify instance
7+
*/
8+
export default function addReqIdContext(server: FastifyInstance): void {
9+
/**
10+
* Sets reqId context for all asynchronous operations within the request
11+
* Uses 'onRequest' hook so context is available in all subsequent hooks and handlers
12+
*/
13+
server.addHook('onRequest', (request, _reply, done) => {
14+
requestContextStorage.run({ reqId: request.id }, () => {
15+
done();
16+
});
17+
});
18+
}

src/repository/storage/postgres/orm/sequelize/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { DatabaseConfig } from '@infrastructure/config/index.js';
22
import { Sequelize } from 'sequelize';
3-
import { getLogger } from '@infrastructure/logging/index.js';
3+
import { getLogger, getRequestLogger } from '@infrastructure/logging/index.js';
44

55
const databaseLogger = getLogger('database');
66

@@ -28,7 +28,8 @@ export default class SequelizeOrm {
2828
this.conn = new Sequelize(this.config.dsn, {
2929
benchmark: true,
3030
logging: (message, timing) => {
31-
databaseLogger.info(
31+
const logger = getRequestLogger('database');
32+
logger.info(
3233
{ durationMs: timing },
3334
message
3435
);

0 commit comments

Comments
 (0)