Подтвердить что ты не робот

За каждый вход в журнал Node.js

Я - опытный разработчик Java, собирающий Node.js и переводящий асинхронную модель. Большинство вещей идут хорошо, за исключением регистрации. Я не могу найти ничего похожего на log4j и NDC в Java при разработке в Node.js с выражением.

Моя цель состоит в том, чтобы каждый оператор журнала автоматически добавлял следующую информацию:

[2013-11-07 11:17: 04.615 serverScript INFO 7036 192.168.7.209]

Это включает временную метку, имя файла js, записывающего этот оператор (для модульных приложений node), уровень отладки, идентификатор процесса (запущенные кластеры) и IP-адрес клиента.

Я могу заставить его написать их, когда они сначала входят в мой обработчик запросов, но не распространяя кучу параметров на каждую вызываемую функцию, в операторах логгера внутри подпрограмм нет информации. Я знаю, что могу создать экземпляр моего регистратора внутри каждого js файла, который инициализирует его имя, но мне еще предстоит выяснить решение для IP-адреса клиента. Для запросов с более длинным запуском адрес, который я установил в моем журнале, перезаписывается, когда приходит следующий запрос, поэтому скрещенные IP-адреса пересекаются.

Я посмотрел на winston, но не смог решить эту проблему даже с ней. Кто-нибудь это сделал? Это очень полезное поле для отслеживания, когда вы можете фильтровать по IP для просмотра только одного действия пользователя.

[edit: тест от решения передачи параметров до тех пор, пока я не изучу способ syslog]

[2013-11-07 14:29:28.641 server INFO  7527 192.168.7.209] Got request from 192.168.7.209 for /ionmed/executeQuery?
[2013-11-07 14:29:28.641 router INFO  7527 192.168.7.209] About to route a request for /ionmed/executeQuery, method=POST
[2013-11-07 14:29:28.642 router INFO  7527 192.168.7.209] getting POSTed data
[2013-11-07 14:29:28.642 router INFO  7527 192.168.7.209] POST params: {"sqlQuery":"select sleep(10)","sessionStart":"1383852558799","rand":"0.5510970998368581","jsessionid":"117DBAA89F599D923AF80D4AB171BDDF"}
[2013-11-07 14:29:28.642 requestHandlers INFO  7527 192.168.7.209] 'query' was called.
[2013-11-07 14:29:28.642 requestHandlers INFO  7527 192.168.7.209] select sleep(10)
[2013-11-07 14:29:30.673 server INFO  7527 192.168.7.217] Got request from 192.168.7.217 for /
[2013-11-07 14:29:30.673 router INFO  7527 192.168.7.217] About to route a request for /, method=GET
[2013-11-07 14:29:30.673 router INFO  7527 192.168.7.217] No request handler found for /; serving as file
[2013-11-07 14:29:30.673 router INFO  7527 192.168.7.217] Request handler 'serveFile' was called to get: /index.html
[192.168.7.217 Thu, 07 Nov 2013 19:29:30 GMT] HTTP/1.1 GET "/node/" 200 "Mozilla/5.0 (iPod; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3"
[2013-11-07 14:29:33.578 server INFO  7527 192.168.7.217] Got request from 192.168.7.217 for /
[2013-11-07 14:29:33.578 router INFO  7527 192.168.7.217] About to route a request for /, method=GET
[2013-11-07 14:29:33.578 router INFO  7527 192.168.7.217] No request handler found for /; serving as file
[2013-11-07 14:29:33.579 router INFO  7527 192.168.7.217] Request handler 'serveFile' was called to get: /index.html
[192.168.7.217 Thu, 07 Nov 2013 19:29:33 GMT] HTTP/1.1 GET "/node/" 200 "Mozilla/5.0 (iPod; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3"
[2013-11-07 14:29:38.644 requestHandlers INFO  7527 192.168.7.209] sending response
[192.168.7.209 Thu, 07 Nov 2013 19:29:38 GMT] HTTP/1.1 POST "/node/ionmed/executeQuery?" 200 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0"
[2013-11-07 14:29:41.540 server INFO  7527 192.168.7.217] Got request from 192.168.7.217 for /
[2013-11-07 14:29:41.541 router INFO  7527 192.168.7.217] About to route a request for /, method=GET
[2013-11-07 14:29:41.541 router INFO  7527 192.168.7.217] No request handler found for /; serving as file
[2013-11-07 14:29:41.541 router INFO  7527 192.168.7.217] Request handler 'serveFile' was called to get: /index.html
[192.168.7.217 Thu, 07 Nov 2013 19:29:41 GMT] HTTP/1.1 GET "/node/" 200 "Mozilla/5.0 (iPod; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B206 Safari/7534.48.3"
[2013-11-07 14:29:45.146 server INFO  7527 192.168.7.209] RLz6tmJ7KTH2R16VCVTX: bye {"user":"1"}
[2013-11-07 14:29:45.176 server INFO  7527 192.168.7.209] RLz6tmJ7KTH2R16VCVTX: disconnected

Теперь мне просто нужно выяснить, как заставить экспресс-регистратор запросов находиться в том же формате записи строки, что и мой внутренний журнал, пока он не будет перемещен в rsyslog.

4b9b3361

Ответ 1

Я попал в эту же проблему некоторое время назад, и, наконец, я мог потратить некоторое время на ее изучение. Подход @ibash и его пост поставили меня впереди, чтобы решить проблему, которую я имел (спасибо за вашу помощь). Я только сделал несколько шагов, чтобы автоматически печатать в журналах уникальный идентификатор для каждого запроса. В вашем случае вы можете добавить исходный и целевой IP-адрес и всю информацию, необходимую для каждого запроса, используя тот же подход и автоматически распечатать его во всех журналах.

Мой подход: - Как пояснил @ibash, я использовал продолжение-локальное хранилище для обмена информацией между всеми модулями для каждого запроса. Поэтому я генерирую уникальный идентификатор для каждого запроса и сохраняю его в пространстве имен, созданных с помощью этой библиотеки - Я обернул библиотеку Winston (очень простым способом), чтобы восстановить информацию из общего пространства имен и переопределить все методы Winston, которые я использую для добавления в строку уникального идентификатора. Очевидно, что в вашем случае вы должны добавить всю необходимую информацию и сохранить ее ранее в пространстве имен библиотеки.

Поскольку проблема была немного сложной, чтобы объяснить, что люди не знакомятся со всеми этими вещами, я записал ее в сообщении с ясным примером того, что вы можете повторно использовать, если хотите. Обертка Winston может быть действительно полезной: Express.js: информация о регистрации с глобальным уникальным идентификатором запроса - Node.js

Надеюсь, вы сможете повторно использовать мой код, и, возможно, в будущем Express реализует для этого решение.

Ответ 2

Эти инструкции были из дистрибутива Ubuntu 12.04, который я установил, но они должны применяться довольно близко к RHEL, Fedora, CentOS и т.д.

Rsyslog - это утилита регистрации системы, которую вы можете использовать для регистрации сообщений из любой программы на машине Linux. Сначала вам нужно найти информацию о конфигурации rsylog. Вы можете сделать это с помощью следующей команды:

sudo find / -name rsyslog.conf

Если вы не можете найти файл конфигурации, вы можете перечислить запущенный сервис, чтобы узнать, существует ли rsyslog даже на вашем компьютере с помощью следующей команды:

service --status-all

Теперь откройте найденный файл и выполните следующие действия:

  • Комментировать строку $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
  • Uncomment $ModLoad imtcp
  • Uncomment $InputTCPServerRun и укажите номер порта 1514, использующий 1514 b/c Ubuntu 12.04 rsyslog имеет проблемы с удалением разрешений, если я использую порт 514, другие дистрибутивы не имеют похожих проблем, и вы можете сохранить порт по умолчанию #. Я обойду это, используя iptables для перенаправления порта 514 трафика на 1514
  • Изменить $FileCreateMode 0640 на 0644

Теперь я создал файл с именем /etc/rsyslog.d/10.conf(это дополнительный файл конфигурации для rsyslog, где мы можем фильтровать сообщение, файлы журналов имен и т.д.) и добавил к нему следующее:

$template DailyPerHostLogs,"/var/log/MyLogFile_%$YEAR%_%$MONTH%_%$DAY%.log"

#:msg,contains,"MsgName" -?DailyPerHostLogs
*.* -?DailyPerHostLogs
&~

Этот файл создает новый файл для каждого дня и находит любое сообщение, отправленное с помощью MsgName в тексте, и помещает его в ежедневный файл, а затем удаляет его из очереди, которая будет регистрироваться любыми другими запросами журнала, чтобы мы не удваивали запишите его.

Теперь вы можете перезагрузить машину, над которой работаете, и все это должно работать. Вы можете проверить это, ища файлы в /var/log, как определено в 10.conf выше. Удалите регистратор из командной строки, выполнив следующие команды:

logger this is from the command line
echo "this is from the tcp port" > /dev/tcp/127.0.0.1/1514

Вы должны увидеть, как эти строки появляются в файле журнала. Если вы это получите, перейдите к модулю node, который сможет попасть в журнал.

var net = require('net');

var client = net.connect({port: this.1514}, function(){ console.log("Open"); });

client.write(' ' + "sMsgName: What"+ ' ' + "hath" + ' ' + "God wrought?" + '\n');

//Do everything else your program needs. . . 

"\n" в записи сообщает rsyslog, что мы закончили с этой строкой. Кроме того, вам нужно будет добавить пространство для фильтрации: http://www.rsyslog.com/log-normalization-and-the-leading-space/

Дьявол всегда находится в деталях с такой настройкой, но я думаю, что это даст вам большую часть пути, и поиск в google поможет вам до конца.

Ответ 3

Отвечая на это, поскольку я просто написал сообщение о том, как использовать keep-local-storage для сохранения "идентификатора транзакции" с каждым журналом (без его ручного распространения). Вы можете сделать то же самое для клиентского ip, идентификатора процесса и т.д.

Следуйте за этим сообщением: https://datahero.com/blog/2014/05/22/node-js-preserving-data-across-async-callbacks/

Но вместо того, чтобы просто сохранить идентификатор транзакции, вам тоже понадобятся: request.connection.remoteAddress и process.pid

Сообщите мне, есть ли у вас какие-либо вопросы здесь или там, и я отвечу им.