🤔 Как не терять requestId в логах не пробрасывая его через параметры методов?
Классическая проблема NodeJS разработки: логи не читаемы. При дебаге когда пользователь один, разобрать что происходит ещё можно. Но после запуска в прод в логах сборная солянка из запросов и восстановить трейс вызова композиции методов нельзя
import { scoped } from "di-scoped"; export interface IRequestContext { userId: string; requestId: string; serviceName: "mobile" | "desktop"; version: number; } export const RequestContextService = scoped( class { constructor(readonly context: IRequestContext) {} } ); export type TRequestContextService = InstanceType< typeof RequestContextService >; export default RequestContextService;
Согласно MVC, делается два слоя: View и Controller. На уровне view кладем requestId в контекст исполнения через
RequestContextService.runInContext
import { inject } from "di-kit"; export class SocketViewService { readonly loggerService = inject<LoggerService>(TYPES.loggerService); readonly socketControllerService = inject<SocketControllerService>(TYPES.socketControllerService); public sendNewOrder = async ( request: TRequest<{ room: string; orderId: string }>, ): Promise<TResponse<SendNewOrder>> => { this.loggerService.log("socketViewService sendNewOrder", { request }); try { const data = await RequestContextService.runInContext( // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ async () => await this.socketControllerService.sendNewOrder(request.data), request, ); return { status: "ok", serviceName: request.serviceName, version: request.version, userId: request.userId, requestId: request.requestId, data }; } catch (error: any) { this.loggerService.log("socketViewService sendNewOrder error", { request, error: errorData(error) }); return { status: "error", error: VerificationError.getErrorMessage(error), errorCode: VerificationError.getErrorCode(error), serviceName: request.serviceName, version: request.version, userId: request.userId, requestId: request.requestId }; } }; }
Voila! Во всех вложенных сервисах к записи в лог будет приложен идентификатор requestId. Дополнительно, этот код позволяет сериализовать ошибки так, чтобы передавать их по шине gRPC
import { inject } from "di-kit"; import { createLogger } from 'pinolog'; const logger = createLogger("socket.log"); export class LoggerService { readonly requestContextService = inject<TRequestContextService>(TYPES.requestContextService); private get context() { if (RequestContextService.hasContext()) { // в лог - только конверт IRequestContext; scoped-контекст. но дебаггеру виден весь запрос const { serviceName, version, userId, requestId } = this.contextService.context; return { serviceName, version, userId, requestId }; } return {}; } public log = (topic: string, ...args: any[]) => { logger.log(topic, ...args, this.context); } }













