Papooch/nestjs-cls

In prisma's $on event, nest-cls did not get normal context data

Closed this issue · 1 comments

app.service.ts

import { Injectable } from '@nestjs/common';
import { logger } from './logger/myLogger.service';
import { PrismaService } from './prisma/prisma.service';

@Injectable()
export class AppService {
  constructor(private prisma: PrismaService) {}
  async getHello(): Promise<string> {
    logger.log('test');
    const row = await this.prisma.user.findFirst({ where: { id: 1 } });
    console.log('row', row);
    logger.log('test-end');
    return 'Hello World!22';
  }
}

prisma.service.ts

import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { Prisma, PrismaClient } from '@prisma/client';
import { logger } from 'src/logger/myLogger.service';

@Injectable()
export class PrismaService
  extends PrismaClient<Prisma.PrismaClientOptions, 'query'>
  implements OnModuleInit, OnModuleDestroy
{
  constructor() {
    super({ log: [{ emit: 'event', level: 'query' }] });
  }
  async onModuleInit() {
    await this.$connect();
    this.$on('query', (event: Prisma.QueryEvent) => {
      let queryMsg = event.query;
      try {
        const params = JSON.parse(event.params) as any[];
        for (const k of params) {
          queryMsg = queryMsg.replace('?', ` ${k} `);
        }
        queryMsg += ';';
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
      } catch (e) {
        queryMsg += `; params ${event.params}`;
      }

      logger.log(`======sql_log=====\n${queryMsg} ${event.duration}ms`);
    });

    this.$use(async (params, next) => {
      console.log(params);
      const before = Date.now();

      const result = await next(params);

      const after = Date.now();

      logger.log(
        `Query ${params.model}.${params.action} took ${after - before}ms`,
      );

      return result;
    });
  }

  async onModuleDestroy() {
    await this.$disconnect();
  }
}

myLogger.service.ts

import {
  ConsoleLogger,
  Global,
  Injectable,
  LoggerService,
  LogLevel,
  Scope,
} from '@nestjs/common';
import { ClsServiceManager } from 'nestjs-cls';
type formatType = {
  level: LogLevel;
};

export class TraceStore {
  traceId: string;

  ua: string;

  reqUrl: string;

  reqMethod: string;

  time: number;
}

@Global()
@Injectable({ scope: Scope.TRANSIENT })
export class MyLogger extends ConsoleLogger implements LoggerService {
  log(...params: unknown[]): void {
    super.log(this.formatParamStyle(params, { level: 'log' }));
  }

  formatParamStyle(messages: unknown[], options: formatType): string {
    const { level } = options;
    const rows: string[] = [];

    const cls = ClsServiceManager.getClsService();
    const trace = cls.get('trace') as TraceStore;

    const time = trace
      ? super.colorize(`+${+new Date() - trace.time}ms`, 'warn')
      : '';

    if (trace) {
      rows.push(trace.traceId, trace.reqUrl, trace.reqMethod);
    }

    for (const message of messages) {
      if (typeof message === 'object') {
        rows.push(JSON.stringify(message));
      } else {
        rows.push(String(message));
      }
    }

    return `${time} ${super.colorize(rows.join(' '), level)}`;
  }
}

export const logger = new MyLogger();

dependencies

"dependencies": {
    "@nestjs/common": "^10.3.2",
    "@nestjs/core": "^10.4.4",
    "@nestjs/platform-express": "^10.4.4",
    "@prisma/client": "5.22.0",
    "nestjs-cls": "^4.4.1",
    "reflect-metadata": "^0.2.1",
    "rxjs": "^7.8.1",
    "uuid": "^11.0.2"
  },

result

traceId is lost when the sql is printed!!

image

Seems to be a bug in Prisma, please see prisma/prisma#20104 and prisma/prisma#23397.

Unfortunately, there's nothing I can do on the library's side to fix this.