NodeJS Express - глобальный уникальный идентификатор запроса

Можно ли определить уникальный идентификатор запроса, который включается в каждый оператор журнала, не передавая регистратор каждому вызову метода / функции?

Используемые технологии: NodeJS, Express, Winston

3 ответа

Решение

отредактированный

Наконец, я создал библиотеку, которая делает всю работу. https://github.com/davicente/express-logger-unique-req-id

Это оболочка библиотеки Winston, поэтому вы можете использовать ее таким же образом.

Дайте мне знать, если это поможет вам


У нас была такая же проблема в нескольких проектах, и я не мог найти полное решение этого вопроса. Мы используем одни и те же технологии (Node.js, Express.js и Winston для журналов). Я нашел решение этой проблемы, используя несколько библиотек и упаковав библиотеку Winston: - node-uuid для создания уникальных идентификаторов для каждого запроса - continueation-local- хранилище для обмена этими идентификаторами между различными модулями без отправки объекта req во всех вызовах.

Сначала мне нужно создать и установить уникальный идентификатор для каждого запроса. Я делаю это в промежуточном программном обеспечении:

var uuid = require('node-uuid');
var createNamespace = require('continuation-local-storage').createNamespace;
var myRequest = createNamespace('my request');

// Run the context for each request. Assign a unique identifier to each request
app.use(function(req, res, next) {
    myRequest.run(function() {
        myRequest.set('reqId', uuid.v1());
        next();
    });
});

После этого мне пришлось обернуть библиотеку Winston, восстановить идентификатор из контекста и добавить в сообщение журнала:

var winston = require('winston');
var getNamespace = require('continuation-local-storage').getNamespace;

// Wrap Winston logger to print reqId in each log
var formatMessage = function(message) {
    var myRequest = getNamespace('my request');
    message = myRequest && myRequest.get('reqId') ? message + " reqId: " + myRequest.get('reqId') : message;
    return message;
};

var logger = {
    log: function(level, message) {
        winstonLogger.log(level, formatMessage(message));
    },
    error: function(message) {
        winstonLogger.error(formatMessage(message));
    },
    warn: function(message) {
        winstonLogger.warn(formatMessage(message));
    },
    verbose: function(message) {
        winstonLogger.verbose(formatMessage(message));
    },
    info: function(message) {
        winstonLogger.info(formatMessage(message));
    },
    debug: function(message) {
        winstonLogger.debug(formatMessage(message));
    },
    silly: function(message) {
        winstonLogger.silly(formatMessage(message));
    }
};
module.exports = logger;

Я думаю, что это было немного сложно, поэтому я решил записать это в посте. Вы можете получить больше информации оттуда: Express.js: регистрация информации с глобальным уникальным идентификатором запроса - Node.js

Я надеюсь, что это поможет с вашей проблемой.

Этот ответ имеет проблему: счетчик возвращается к 0 каждый раз, когда процесс узла перезапускается. Оказывается, там довольно просто обойти. Вы просто добавляете промежуточное программное обеспечение Express, которое помечает каждый запрос, вызванный UUID, с помощью пакета uuid.

Для UUID Pre-2.0

const uuid = require('uuid');
const app = express();
app.use(function (req, next) {
  req.id = uuid.v4();
  next();
});

Для uuid 3.0+

const uuidv4 = require('uuid/v4');
const app = express();
app.use(function (req, next) {
  req.id = uuidv4();
  next();
});

В самом начале обработки вашего запроса добавьте что-то вроде следующего (или поместите его в свой собственный файл):

var makeID = (function() {
  var index = 0;
  return function() {
   return index++;
  }
})();

app.use(function(req, res, next) {
  req.id = makeID()
  next()
})

Это даст каждому запросу уникальный (последовательный) идентификатор. Не позволяйте людям идентифицировать себя с этим, только используйте это внутренне!

При входе в Winston вы можете ввести метаданные, которые будут отображаться после сообщения (в форме ${name}=${value}), который выглядит так

app.use(function(req, res) {
  winston.log('info', 'Test Log Message', { id: req.id });
  res.end("Done.")
});

Надеюсь, это полезно.

Другие вопросы по тегам