1

我正在使用fastifywithnext.js并且我需要包括跟踪(requestId到目前为止是问题)。我现在正在做的是创建一个fastifyonRequest 钩子并生成一个requestId值并将其设置在请求对象中(也可以作为请求标头)。我想要访问这个请求对象有两个原因:

  1. 在记录器对象中(pino在这种情况下,我想requestId在所有自定义服务器端日志中包含 )。
  2. 在需要向其他服务发出的所有请求中,都需要包含requestIdin 标头。

也许我错过了一些微不足道的事情,而且我没有以最好的方式做到这一点。

这里有一些片段

这就是我生成 reqId 的方式

const fastify = fastifyFactory({
  logger, // logger configuration (Pino instance with custom configuration, see below)
  genReqId: () => {
    return Math.random()
      .toString(36)
      .slice(-6);
  }
});

皮诺实例

const pino = require('pino');
const logger = pino({
  messageKey: 'message',
  prettyPrint: true,
  changeLevelName: 'severity',
  useLevelLabels: true,
  base: {
    serviceContext: {
      service: 'web'
    }
  },
  level:'info'
});
module.exports = {
  logger
};

这是一个插件,用于获取生成的 reqId 并将其设置为请求对象中的查询属性

const tracing = function tracing(fastify, opt, next) {
  fastify.addHook('onRequest', (req, res, nextRequest) => {
    const { id } = req;
    const logger = fastify.log.child({ reqId: id });
    req.query.reqId = id;
    fastify.log = logger; //overrides the current fastify logger to include the reqId in all custom logs
    nextRequest();
  });
  next();
};
tracing[Symbol.for('skip-override')] = true;
module.exports = tracing;

使用时我没有问题,fastify.log.info(...)因为在每个请求中如何覆盖记录器,它将包含reqId作为子日志。问题是我想创建一个通用记录器以在任何部分使用,而 Fastify 记录器在 React 组件中不可用(例如在 处写入日志getInitialProps)。另一个重要的想法是我需要reqId在我发送给其他服务的所有请求中包含这个(例如:在获取数据时),这就是为什么我尝试将此值存储在请求对象中但需要获取它的原因。

4

1 回答 1

0

从项目构建开始:

npx create-next-app --example custom-server-fastify custom-server-fastify-app

并改变server.js

const Next = require('next')
const Fastify = require('fastify')

// your pino config
const fastify = Fastify({
  logger: {
    level: 'info',
    prettyPrint: true,
    changeLevelName: 'severity',
    useLevelLabels: true,
    base: {
      serviceContext: {
        service: 'web'
      }
    }
  },
  genReqId: () => { return Math.random().toString(36).slice(-6) }
})

// your plugin
const aPlugin = function yourPlugin (fastify, opts, next) {
  fastify.addHook('onRequest', (request, reply, next) => {
    request.log.info('hello')
    const { id } = request
    request.query.reqId = id
    next()
  })
  next()
}
aPlugin[Symbol.for('skip-override')] = true
fastify.register(aPlugin)

[.... other generated code]
const port = parseInt(process.env.PORT, 10) || 3000

[.... other generated code]
      fastify.get('/*', (req, reply) => {
        console.log('-------->', req.id, req.query.reqId) // both your id is ok
        return app.handleRequest(req.req, reply.res).then(() => {
          reply.sent = true
        })
[.... other generated code]
      })

然后:

npm run dev
# another console
curl http://localhost:3000/

它将打印出:

[1558441374784] INFO : Server listening at http://127.0.0.1:3000
    serviceContext: {
      "service": "web"
    }
> Ready on http://localhost:3000
[1558441405416] INFO : incoming request
    serviceContext: {
      "service": "web"
    }
    reqId: "2i810l"
    req: {
      "method": "GET",
      "url": "/",
      "hostname": "localhost:3000",
      "remoteAddress": "127.0.0.1",
      "remotePort": 57863
    }
req id ----> 2i810l
--------> 2i810l 2i810l
[ event ] build page: /
[ wait ]  compiling ...
[1558441406171] INFO : request completed
    serviceContext: {
      "service": "web"
    }
    reqId: "2i810l"
    res: {
      "statusCode": 200
    }
    responseTime: 753.012099981308

所以我认为误解在于请求对象是 Fastify 请求,而不是 Node.js “低级”请求对象,可以使用request.req.

此外,运行fastify.log = logger;是危险的,因为这意味着每个请求都会覆盖并创建一个新的记录器并为 fastify 实例更改记录器,这是不安全的,并且如图所示没有必要。

如果您想要更多子记录器(每个示例的每个路由前缀),我建议您探索/使用onRegisterhook


编辑:

现在自定义挂钩打印:

[1558443540483] INFO : hello
    serviceContext: {
      "service": "web"
    }
    reqId: "zjuhw2"
于 2019-05-21T12:30:44.227 回答