Node.js выражать запрос Id
Я пытаюсь создать какой-то идентификатор запроса для ведения журнала, который будет доступен мне через каждую функцию потока запросов. Я хочу регистрировать каждый шаг потока запросов с идентификатором, указывающим, какая строка журнала для какого запроса.
Я просмотрел некоторые идеи и столкнулся с двумя основными предложениями:
Первое - это создание промежуточного программного обеспечения, которое добавит поле в объект 'req', как это (как предложено здесь):
var logIdIterator = 0;
app.all('*', function(req, res, next) {
req.log = {
id: ++logIdIterator
}
return next();
});
И второй использует continuation-local-storage
Проблемы:
Для первого подхода - это означает, что мне придется передать дополнительный аргумент каждой функции в потоке, и это нелегкое решение для использования над зрелым приложением с бесчисленными API и потоками.
Второй выглядит многообещающим, но, к сожалению, он имеет некоторые проблемы, в которых государство теряется (см. здесь).
Кроме того, это произошло несколько раз, когда мы использовали нашу библиотеку redis - что плохо, потому что запросы redis происходят в каждом из наших потоков.
Я думаю, если я не найду другого решения, мне придется использовать первый подход, просто я хочу избежать передачи дополнительного параметра тысячам существующих функций.
Мой вопрос: как вы предлагаете поддерживать идентификатор запроса через поток запросов?
Ответы
Ответ 1
Вы могли бы сделать свою первоначальную рутину немного более сложной: (а) хранить информацию в виде файла cookie только для сервера и (б) помещать больше информации в файл cookie за пределы счетчика. Например, я использую следующее как трассировку всех вызовов в моем приложении:
console.log('['+count+'] at: '+format.asString('hh:mm:ss.SSS', new Date())+' Url is: ' + req.url);
где "count" увеличивается с начала приложения (да, лучше использовать постоянный синглтон). Это дает мне каждый вызов сервера (req.url) и точно, когда этот вызов был сделан. Это можно легко расширить, чтобы забрать sessionID, если ваше приложение выполняет управление уровнем сеанса.
Ответ 2
Вы можете использовать этот пакет: https://www.npmjs.com/package/express-request-id
Это промежуточное программное обеспечение, которое будет добавлять uuid для каждого запроса
var app = require('express')();
var addRequestId = require('express-request-id')();
app.use(addRequestId);
app.get('/', function (req, res, next) {
res.send(req.id);
next();
});
app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});
// curl localhost:3000
// d7c32387-3feb-452b-8df1-2d8338b3ea22
Ответ 3
У вас асинхронная связь, и вы хотите сохранить контекст без а) закрытия или b) передачи параметров. Я боюсь, что лучше всего передать что-то ко всем функциям, которые нужно знать - будь то объект req
, идентификатор запроса, вызов функции curried log
- что-то.
Независимо от того, что вы проходите, можно легко переделать в любой из других - простой идентификатор может искать объект из глобального хранилища (например, не хорошо, но возможно). Имея это в виду - у вас уже может быть что-то переданное методам, которые однозначно идентифицируют запрос; в этом случае, используя это как ключ и просматривая дополнительные данные из глобального хранилища (т.е. require
файл с module.exports.cache = new Map();
или что-то не повод для загрязнения глобального пространства имен).
Как вы заметили, попытки делать неуловимые вещи с языком часто бывают хрупкими (особенно когда встречаются другие неуклюжие вещи). Тем не менее, вы можете понять, как continuation-local-storage
работает внутри, отлаживает его вместе с вашими библиотеками и использует его или homebrew-решение.
Звучит неудобно со стоимостью поддержания этого кода. Это запах кода - и добавление неявного глобального продолжения локального состояния звучит как нечто, что только поможет понять и удержать код, более сложный, чем простой. Вы можете принять это как возможность обучения и спросить, почему вам нужен идентификатор запроса, и почему он не нужен, когда кто-нибудь написал код. Мне жаль, что, не зная самой кодовой базы, это лучший ответ, который я могу дать.