Можно ли получить объект запроса next.js глобально?
Я использую fastify
с next.js
и мне нужно включить трассировку (requestId
это проблема до сих пор). То, что я делаю сейчас, это создание fastify
OnRequest хук и генерация requestId
значение и установка его в объекте запроса (также может быть как заголовок запроса). Я хочу получить доступ к этому объекту запроса по двум причинам:
- В логгере объект (
pino
в этом случае я хочу включитьrequestId
во всех пользовательских журналах на стороне сервера). - Во все запросы, которые необходимо направлять другим службам, необходимо указывать
requestId
в заголовках.
Может быть, я упускаю что-то тривиальное, и я делаю это не лучшим образом.
ЗДЕСЬ НЕКОТОРЫЕ ОТКРЫТКИ
Вот как я генерирую 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
во всех запросах, которые я отправляю другим службам (например, при извлечении данных), именно поэтому я пытался сохранить это значение в объекте запроса, но мне нужно его получить.
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
крюк
РЕДАКТИРОВАТЬ:
Теперь пользовательский крючок печати:
[1558443540483] INFO : hello
serviceContext: {
"service": "web"
}
reqId: "zjuhw2"