首页 > 解决方案 > 如何在 Loopback 4 中跟踪请求 ID?

问题描述

我正在尝试使用 Loopback 4 在我的 REST API 中跟踪每个 HTTP 请求,以便使用 log4js 将它们记录到控制器中,就像这样:

[2020-05-05T19:21:52.191] [INFO] [request-id:47e9a486-1243-1c07-3ac0-0acc9cce2c0e] user.controller.ts - starting request validation
[2020-05-05T19:21:52.191] [INFO] [request-id:1dc81e45-093a-8009-42d2-e545c3a10c9d] user.controller.ts - starting request validation
[2020-05-05T19:21:53.126] [INFO] [request-id:47e9a486-1243-1c07-3ac0-0acc9cce2c0e] user.controller.ts - request validation success
[2020-05-05T19:21:53.145] [ERROR] [request-id:1dc81e45-093a-8009-42d2-e545c3a10c9d] user.controller.ts - request validation failed

这里的主要问题[request-id:UUID]部分,因为 Node.js 有时会混淆日志,我无法识别它们中的哪些属于同一个请求。我已经为 Express 应用程序找到了一些解决方案,但是我找不到一种方法来使用 Loopback 4 和 log4js:

该解决方案可能涉及使用序列处理程序,但我还不知道如何去做。注入 Request 对象的一些提示:https ://github.com/strongloop/loopback-next/issues/1881#issuecomment-431384142

标签: node.jsstronglooploopbackloopback4log4js-node

解决方案


我们使用 winston logger 来完成它,它作为 Logger Service 注入到我们的 sequence.ts 中。这是 sequence.ts 的代码。

export class MySequence implements SequenceHandler {
  constructor(
    @inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
    @inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams,
    @inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
    @inject(SequenceActions.SEND) public send: Send,
    @inject(SequenceActions.REJECT) public reject: Reject,
    @inject(LOGGER.LOGGER_INJECT) public logger: ILogger,
    @inject(HelmetSecurityBindings.HELMET_SECURITY_ACTION)
    protected helmetAction: HelmetAction,
    @inject(RateLimitSecurityBindings.RATELIMIT_SECURITY_ACTION)
    protected rateLimitAction: RateLimitAction,
    @inject(AlivioBindings.i18n)
    protected i18n: i18nAPI,
  ) {}

  async handle(context: RequestContext) {
    const requestTime = Date.now();
    try {
      const {request, response} = context;
      this.logger.info(
        `Request ${request.method} ${
          request.url
        } started at ${requestTime.toString()}.
        Request Details
        Referer = ${request.headers.referer}
        User-Agent = ${request.headers['user-agent']}
        Remote Address = ${request.connection.remoteAddress}
        Remote Address (Proxy) = ${request.headers['x-forwarded-for']}`,
      );
      const route = this.findRoute(request);
      const args = await this.parseParams(request, route);

      await this.rateLimitAction(request, response);
      await this.helmetAction(request, response);

      request.body = args[args.length - 1];
      const result = await this.invoke(route, args);
      this.send(response, result);
    } catch (err) {
      this.logger.error(
        `Request ${context.request.method} ${
          context.request.url
        } errored out. Error :: ${JSON.stringify(err)} ${err}`,
      );

      this.reject(context, error);
    } finally {
      this.logger.info(
        `Request ${context.request.method} ${
          context.request.url
        } Completed in ${Date.now() - requestTime}ms`,
      );
    }
  }
}

您可以在此处使用任何记录器作为提供程序。您可以在 log4js 上创建一个包装器提供程序,然后像上面那样做。希望这可以帮助。如果您也想查看提供程序代码,请告诉我。我也会分享的。


推荐阅读