当我无法在本地重现错误时,如何调试 nestjs 应用程序?

How can I debug a nestjs application when I cannot reproduce the error locally?

提问人:Sébastien 提问时间:9/23/2022 最后编辑:Jay McDonielSébastien 更新时间:9/23/2022 访问量:680

问:

我有一个 nestjs 应用程序,可以处理一些营销自动化任务。 我已经设置了 datadog 和 sentry,但不断出现错误。 当我在本地重播身体时,我没有收到任何错误。我有点被困在这里。

我在哨兵上得到的错误如下(我正在将错误字符串化为附加数据)

{
  "success": false,
  "message": "Bad Request",
  "errorCode": 400,
  "context": {
    "req": {
      "method": "PUT",
      "url": "https://api.pipedrive.com/v1/persons/84653?api_token=my_token",
      "data": {},
      "headers": {
        "user-agent": "Pipedrive-SDK-Javascript-16.0.3",
        "content-type": "application/json",
        "accept": "application/json"
      }
    },
    "header": {
      "date": "Thu, 22 Sep 2022 22:01:46 GMT",
      "content-type": "application/json",
      "transfer-encoding": "chunked",
      "connection": "close",
      "cf-ray": "74ee5231de24f40b-LHR",
      "access-control-allow-origin": "*",
      "cache-control": "no-cache",
      "content-encoding": "gzip",
      "strict-transport-security": "max-age=31536000; includeSubDomains",
      "vary": "Accept-Encoding",
      "cf-cache-status": "DYNAMIC",
      "access-control-expose-headers": "X-RateLimit-Remaining, X-RateLimit-Limit, X-RateLimit-Reset",
      "badi": "Routing: eu-central-1=>eu-central-1; Version: 8cce; Host: bari;",
      "x-content-type-options": "nosniff",
      "x-correlation-id": "5ccf217c-aee7-4d8f-ab89-70277fb5b4f7",
      "x-daily-requests-left": "6918",
      "x-frame-options": "SAMEORIGIN",
      "x-ratelimit-limit": "40",
      "x-ratelimit-remaining": "37",
      "x-ratelimit-reset": "2",
      "x-xss-protection": "1; mode=block",
      "set-cookie": [
        "__cf_bm=bqPOYf9wW8omTTIvIQnhXgCqxmqexoZCvl0tRkmINBo-1663884106-0-AWQN9mC/Fq+ELcoe7Pfp2aTXcv9JapLJYfrMsUbE3+lOJGgva9hLWHPLGy97S7tDNszaDW5tew4//3R2mVz9bcI=; path=/; expires=Thu, 22-Sep-22 22:31:46 GMT; domain=.pipedrive.com; HttpOnly; Secure; SameSite=None"
      ],
      "server": "cloudflare",
      "alt-svc": "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400"
    },
    "status": 400,
    "text": "{\"success\":false,\"error\":\"Bad request\",\"error_info\":\"Please check developers.pipedrive.com for more information about Pipedrive API.\",\"data\":null,\"additional_data\":null}"
  },
  "errorInfo": "Please check developers.pipedrive.com for more information about Pipedrive API."
}

这似乎与在具有空主体的管道驱动器上发出 PUT 请求有关。

但是,我的代码如下:

  async updatePerson(id: number, person: IPipedrivePersonDto): Promise<PipedrivePerson> {
    if (isEmpty(person)) {
      throw new Error(`Can't update a person with no body`);
    }
    const personApi = new this.pipeDriveClient.PersonsApi();
    const opts = Pipedrive.UpdatePerson.constructFromObject(person);

    if (isEmpty(opts)) {
      throw new Error(`Can't update a person with no body: ` + JSON.stringify(person));
    }

    const { data } = (await personApi.updatePerson(id, opts)) as PersonResponse;

    return data;
  }

当我欺骗我的身体得到一个空的身体时,它就会被抓住。

所以现在,sentry 没有给我整个堆栈跟踪,即执行的代码行列表。这可能会对我有所帮助。

我怎样才能得到它? 我还能如何调试我无法重现的内容? 我还怀疑 pipedrive 节点 js 客户端会发出一些隐藏的 PUT 请求,因为在我的代码中只有上述代码片段可以处理它。

这是我在 nestjs 上的 http 异常过滤器的完整代码,也许我可以以某种方式 pipm 它以获取更多详细信息:

import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common';
import { SentryService } from '@ntegral/nestjs-sentry';
import { Request, Response } from 'express';
import { CustomLoggerService } from 'src/core/logger/logger.service';
import { PipedriveResponseException } from 'src/thirdParties/pipedrive/pipedrive.exception';
import { SlackResponseException } from 'src/thirdParties/slack/slack.exception';
import { injectRecord } from 'src/utils/datadog';

@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
  constructor(private readonly sentry: SentryService, private readonly logger: CustomLoggerService) {}

  private logAndSendResponse(
    exception: PipedriveResponseException | HttpException,
    request: Request,
    response: Response,
    jsonResponse: object,
    message: string | null,
    status: number,
  ) {
    const record = injectRecord({ ...jsonResponse, stack: exception.stack }, 'error');

    this.logger.logger.error(`${request.method} ${request.originalUrl}`, record, exception);

    this.sentry.instance().setExtra('response', jsonResponse);
    this.sentry.instance().setTag('message', message);

    response.status(status).json(jsonResponse);
  }

  catch(exception: PipedriveResponseException | HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    const pipeDriveException = exception as PipedriveResponseException;
    const slackException = exception as unknown as SlackResponseException;
    const globalException = exception as HttpException;

    const baseResponse = {
      timestamp: new Date().toISOString(),
      path: request.url,
    };

    this.sentry.instance().setTag('url', request.url);
    this.sentry.instance().setTag('method', request.method);
    this.sentry.instance().setExtra('stringified-error', JSON.stringify(exception));

    // Catch slack exceptions
    if (slackException.code && slackException.data?.error) {
      const status = 400;
      const message = slackException?.data?.error || null;
      const jsonResponse = {
        ...baseResponse,
        statusCode: status,
        message: message,
      };

      this.logAndSendResponse(exception, request, response, jsonResponse, message, status);
      // Catch pipedrive exceptions
    } else if (pipeDriveException.context && pipeDriveException.errorCode && pipeDriveException.errorInfo) {
      const status = pipeDriveException.errorCode;
      const message = pipeDriveException.context?._body?.error || null;
      const jsonResponse = {
        ...baseResponse,
        statusCode: status,
        message: message,
      };

      this.logAndSendResponse(exception, request, response, jsonResponse, message, status);
    } else {
      const jsonResponse = {
        ...baseResponse,
        exception,
      };

      this.logAndSendResponse(exception, request, response, jsonResponse, globalException.message, 500);
    }

    this.sentry.instance().captureException(exception);
  }
}

感谢您的帮助:)

JavaScript 调试 异常 nestjs pipedrive-api

评论


答: 暂无答案