【问题标题】:It's possible to get next.js request object globally?可以全局获取 next.js 请求对象吗?
【发布时间】:2019-05-21 06:40:04
【问题描述】:

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

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

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

这里有一些片段

这就是我生成 reqId 的方式

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

pino 实例

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(例如:在获取数据时),这就是为什么我尝试将此值存储在请求对象中但需要获取它的原因。

【问题讨论】:

  • 我觉得这个功能已经被genreqid支持了,你试过了吗?
  • @ManuelSpigolon 是的,但此功能允许设置自定义函数来生成 reqId。我目前正在使用,但问题是我无法访问这个属性(reqId),这超出了 fastify 记录器的范围。我尝试使用 cls-hooked 来存储生成的 reqId,但我无法从任何 React 组件中使用它(可能做错了什么)
  • 你有一些sn-p让我更好地理解上下文吗?
  • @ManuelSpigolon 我已经在问题中添加了 sn-ps
  • 我有一个工作的 sn-p,最后一件事:你能添加你的 pino 配置吗?

标签: next.js fastify


【解决方案1】:

从项目构建开始:

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 实例的记录器,这是不安全的,并且如图所示没有必要。

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


编辑:

现在自定义挂钩打印:

[1558443540483] INFO : hello
    serviceContext: {
      "service": "web"
    }
    reqId: "zjuhw2"

【讨论】:

  • 这个问题没有解决。 fastify.log = logger; 的目的是因为如果您尝试编写自定义日志,您将看到 reqId 不包括在内(不是快速写入的默认日志,如传入请求和请求已完成,您展示的那些与 reqId 包括在内)我需要它。这是我的主要问题(可能不是很清楚,对不起我的英语),即使在 React 组件中如何获取这个 reqId
  • 好的,我去看看?
  • I have update the response to print the reqId when you log something 编辑答案以修复此问题仍在检查 React 组件中的 id
  • 在 pino 中 genReqId: () => { return Math.random().toString(36).slice(-6) } 的问题是会生成一个新的 reqId。如果你运行所有你会发现自定义日志的 reqId 与 fastify 日志的 reqId 不同,并且需要相同,因为它们在同一个请求中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-31
  • 2013-07-05
相关资源
最近更新 更多