Можно ли получить объект запроса next.js глобально?

Я использую fastify с next.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);
  }
});

Пино экземпляр

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"
Другие вопросы по тегам