它';是否可以全局获取next.js请求对象?
我正在将它';是否可以全局获取next.js请求对象?,next.js,fastify,Next.js,Fastify,我正在将fastfy与next.js一起使用,我需要包括跟踪(requestId是目前的问题)。我现在正在做的是创建一个fastfyonRequest钩子,生成一个requestId值,并在request对象中设置它(也可以作为请求头)。我想要访问此请求对象的原因有两个: 在logger对象中(pino在本例中,我希望在所有自定义服务器端日志中包含requestId) 在所有需要向其他服务发出的请求中,需要在标题中包含requestId 也许我错过了一些琐碎的事情,我没有用最好的方式去做 这里是
fastfy
与next.js一起使用,我需要包括跟踪(requestId
是目前的问题)。我现在正在做的是创建一个fastfy
onRequest钩子,生成一个requestId
值,并在request对象中设置它(也可以作为请求头)。我想要访问此请求对象的原因有两个:
在logger对象中(pino
在本例中,我希望在所有自定义服务器端日志中包含requestId
)
在所有需要向其他服务发出的请求中,需要在标题中包含requestId
也许我错过了一些琐碎的事情,我没有用最好的方式去做
这里是一些片段
这是我生成请求ID的方式
const fastfy=fastfyFactory({
记录器,//记录器配置(具有自定义配置的Pino实例,请参阅下文)
genReqId:()=>{
return Math.random()
.托斯特林(36)
.切片(-6);
}
});
引脚实例
const pino=require('pino');
常数记录器=引脚({
messageKey:'消息',
打印前:正确,
changeLevelName:“严重性”,
useLevelLabels:true,
基数:{
serviceContext:{
服务:“网络”
}
},
级别:'info'
});
module.exports={
记录器
};
这是一个插件,用于获取生成的reqId并将其设置为请求对象中的查询属性
const tracing=函数跟踪(fastfy、opt、next){
fastfy.addHook('onRequest',(req、res、nextRequest)=>{
常量{id}=req;
const logger=fastfy.log.child({reqId:id});
req.query.reqId=id;
fastfy.log=logger;//覆盖当前的fastfy记录器,以便在所有自定义日志中包含reqId
nextRequest();
});
next();
};
跟踪[Symbol.for('skip-override')]=true;
module.exports=跟踪;
我在使用fastfy.log.info(…)
时没有问题,因为如何在每个请求中覆盖记录器,它将包含reqId
作为子日志。问题是,我想创建一个通用记录器用于任何部件,而fastify logger在React组件中不可用(例如,在getInitialProps
中写入日志)。另一个重要的想法是,我需要在我发送给其他服务的所有请求(例如:获取数据时)中包含此reqId
,这就是为什么我试图将此值存储在请求对象中,但需要获取它。从以下项目构建开始:
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]
})
然后:
它将打印出:
[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
因此,我认为误解在于request对象是fastfy请求,而不是Node.js“low-level”请求对象,它可以通过request.req
访问
此外,运行fastfy.log=logger
是危险的,因为它意味着每个请求都会覆盖并创建一个新的记录器,并更改fastify实例的记录器,这是不安全的,如图所示,这是不必要的
如果您想要更多的子记录器(每个示例的每个路由前缀),我建议探索/使用
编辑:
现在,自定义钩子打印:
[1558443540483] INFO : hello
serviceContext: {
"service": "web"
}
reqId: "zjuhw2"
从具有以下内容的项目构建开始:
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]
})
然后:
它将打印出:
[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
因此,我认为误解在于request对象是fastfy请求,而不是Node.js“low-level”请求对象,它可以通过request.req
访问
此外,运行fastfy.log=logger
是危险的,因为它意味着每个请求都会覆盖并创建一个新的记录器,并更改fastify实例的记录器,这是不安全的,如图所示,这是不必要的
如果您想要更多的子记录器(每个示例的每个路由前缀),我建议探索/使用
编辑:
现在,自定义钩子打印:
[1558443540483] INFO : hello
serviceContext: {
"service": "web"
}
reqId: "zjuhw2"
我想这项功能已经被via支持了,你试过了吗?@ManuelSpigolon是的,但是这项功能允许设置一个自定义函数来生成reqId。我目前正在使用,但问题是在fastify logger的范围之外,我无法访问此属性(reqId)。我尝试使用cls hooked来存储生成的reqId,但我无法从任何React组件使用它(可能是做错了什么)。您是否有一些片段让我更好地理解上下文?@ManuelSpigolon我已经在问题中添加了片段我有一个工作片段,最后一件事:你能添加你的pino配置吗?我想这项功能已经被via支持了,你试过了吗?@ManuelSpigolon是的,但这项功能允许设置一个自定义函数来生成reqId。我目前正在使用,但问题是在fastify logger的范围之外,我无法访问此属性(reqId)。我尝试使用cls hooked来存储生成的reqId,但我无法从任何React组件使用它(可能是做错了什么)。您是否有一些片段让我更好地理解上下文?@ManuelSpigolon我已经在问题中添加了片段我有一个工作片段,最后一件事:你能添加你的pino配置吗?这个问题并没有解决。fastfy.log=记录器的用途代码>是因为如果您尝试编写自定义日志,您将看到未包含reqId(不是fastify写入的默认日志,如传入请求和请求完成,您显示的那些日志与包含reqId的日志配合良好),我需要它。这是我的主要问题(可能不太清楚,对不起我的英语),如何在React组件中获得此reqId OK,我将签出我已更新响应以在您记录某些内容时打印reqId
编辑答案以修复此问题,仍然在React组件中检查id genReqId:()=>{return Math.random()皮诺中的切片(-6)}是将基因