- Оригинальный адрес:A Guide to Node.js Logging
- Оригинальный автор:dkundel
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:fireairforce
Когда вы начинаете работать с JavaScript, первое, чему вы должны научиться, — это передаватьconsole.log()Записывать вещи в консоль. Если вы ищете, как отлаживатьJavaScript, вы найдете сотни сообщений в блогах и статей о StackOverflow, которые расскажут вам об очень «простом» использованииconsole.log()для завершения отладки. Поскольку это такая распространенная практика, мы даже начали использоватьlinterправила, такие какno-console, чтобы гарантировать, что мы не оставим непредвиденные записи в производственном коде. Но что, если мы действительно хотим записать что-то, чтобы предоставить больше информации?
В этом сообщении блога я расскажу о некоторых различных ситуациях, когда вы хотите регистрировать информацию, и о том, как это сделать в Node.js.console.logиconsole.errorи как отправить журнал в библиотеку, не затрагивая консоль пользователя.
console.log(`Let's go!`);
Сначала теория: важные детали Node.js
Хотя вы можете использовать в браузере и Node.jsconsole.logилиconsole.error, но при работе с Node.js следует помнить одну важную вещь. в названномindex.jsфайл напишите следующий код:
console.log('Hello there');
console.error('Bye bye');
а затем использовать в терминалеnode index.jsчтобы запустить его, вы увидите эти два вывода непосредственно ниже:
Однако, хотя они могут выглядеть одинаково, система на самом деле обрабатывает их по-разному. если ты пойдешь проверишьВ документации Node.jsconsoleчасть,ты увидишьconsole.logэто использоватьstdoutпечататьconsole.errorиспользоватьstderrпечатать.
Каждый процесс может использовать три значения по умолчанию.streamsприходить на работу. они соответственноstdin,stdoutиstderr.stdinПотоки для обработки вывода, связанного с вашим процессом. Например, нажатие кнопки или перенаправление вывода (мы сделаем это через секунду).stdoutПотоки используются для вывода вашего приложения. Наконецstderrдля сообщений об ошибках. Если вы хотите знатьstderrпочему он существует и когда его использовать,Вы можете просмотреть эту статью.
Короче говоря, это позволяет нам использовать перенаправление(>) и труба (|) для обработки ошибок и диагностической информации отдельно от фактических результатов приложения. Несмотря на то что>позволяет нам перенаправить вывод команды в файл,2>позвольте намstderrВывод перенаправляется в файл. Например, следующая команда передаст «Привет!»hello.logфайл и передать «До свидания» файлу с именемerror.logв файле.
node index.js > hello.log 2> error.log
Когда вы хотите записаться?
Теперь, когда мы рассмотрели основные аспекты ведения журналов, давайте поговорим о различных вариантах использования, в которых вам может понадобиться что-то регистрировать. Обычно эти варианты использования попадают в одну из следующих категорий:
- Быстрая отладка неожиданного поведения во время разработки
- Браузерная аналитика или ведение журнала диагностики
- использоватьЖурналы серверных приложенийдля регистрации входящих запросов и любых сбоев, которые могли произойти
- Дополнительные журналы отладки для библиотек, чтобы помочь пользователям решить проблемы
- использоватьвывод командной строкидля печати хода выполнения, подтверждающих сообщений или ошибок
В этом блоге мы пропустим первые две категории и сосредоточимся на трех последних, основанных на Node.js.
Журналы вашего серверного приложения
Есть много причин, по которым вам может понадобиться регистрация на сервере. Например, регистрируйте входящие запросы, чтобы вы могли извлечь из них информацию, например, сколько пользователей получают ошибки 404, какими могут быть эти запросы или что они используют.User-Agent. Вы также хотите знать, когда что-то пошло не так и почему.
Если вы хотите попробовать следующее в этой части статьи, сначала обязательно создайте папку. В каталоге проекта создайте файл с именемindex.jsфайл, затем используйте следующий код, чтобы инициализировать весь проект и установить егоexpress:
npm init -y
npm install express
Затем настройте сервер с промежуточным ПО, просто нужноconsole.logдля обслуживания каждого запроса. Поместите следующее вindex.jsВнутри файла:
const express = require('express');
const PORT = process.env.PORT || 3000;
const app = express();
app.use((req, res, next) => {
console.log('%O', req);
next();
});
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(PORT, () => {
console.log('Server running on port %d', PORT);
});
мы используемconsole.log('%O', req)записать весь объект.console.logИспользование под капотомutil.format, который также поддерживает%Oи другие заполнители. ты сможешьПрочтите их в документации Node.js.
когда ты бежишьnode index.jsЗапустите сервер и перейдите кhttp://localhost:3000, вы заметите, что он выведет много информации, которая нам на самом деле не нужна.
Если вы измените код наconsole.log('%s', req)Мы также не получим много информации без вывода всего объекта.
Мы могли бы написать собственную функцию печати, которая просто выводила бы то, что нас интересует, но давайте сделаем шаг назад и обсудим то, что нас обычно волнует. Хотя эта информация часто находится в центре нашего внимания, на самом деле нам может понадобиться другая информация. Например:
- Временная метка - раньше знала, когда что-то произошло
- имя компьютера/сервера - если вы используете распределенную систему
- Идентификатор процесса - если вы используете что-то вроде
pm2инструмент для запуска нескольких процессов Node. - message - фактическое сообщение с некоторым содержимым
- трассировка стека - на случай, если мы зарегистрируем ошибку
- возможно, некоторые дополнительные переменные/информация
Кроме того, поскольку мы знаем, что все идет кstdoutиstderr, то нам могут понадобиться разные уровни логов и возможность настраивать и фильтровать логи на их основе.
Мы можем получить доступ к различным разделамprocessи написать целую кучу кода JavaScript, чтобы получить это, но самое лучшее в Node.js то, что мы получаемnpmэкосистемы, и в нашем распоряжении уже есть множество библиотек. Некоторые из них:
лично мне нравитсяpinoЭта библиотека, поскольку она работает быстро и имеет лучшую экосистему, давайте посмотрим, как ее использовать.pinoПриходите помочь нам войти. Мы также можем использоватьexpress-pino-loggerpackage, чтобы помочь нам аккуратно регистрировать запросы.
Установить одновременноpinoиexpress-pino-logger:
npm install pino express-pino-logger
затем обновитеindex.jsфайл для использования регистратора и промежуточного ПО:
const express = require('express');
const pino = require('pino');
const expressPino = require('express-pino-logger');
const logger = pino({ level: process.env.LOG_LEVEL || 'info' });
const expressLogger = expressPino({ logger });
const PORT = process.env.PORT || 3000;
const app = express();
app.use(expressLogger);
app.get('/', (req, res) => {
logger.debug('Calling res.send');
res.send('Hello World');
});
app.listen(PORT, () => {
logger.info('Server running on port %d', PORT);
});
В этом фрагменте кода мы передаемpinoсоздалloggerэкземпляр и передать егоexpress-pino-loggerдля создания нового промежуточного программного обеспечения и передачиapp.useназвать это. Кроме того, где мы запускаем сервер сlogger.infoзаменитьconsole.log, и добавим строку к нашему маршрутуlogger.debugдля отображения дополнительного уровня журнала.
если прошлоnode index.jsЗапустите сервер перезапуска еще раз, и вы увидите совершенно другой вывод, который печатает JSON для каждой строки. Перейдите снова кhttp://localhost:3000, вы увидите еще одну добавленную строку JSON.
Если вы изучите этот JSON, вы увидите, что он содержит всю ранее упомянутую информацию, например временные метки. Вы также можете заметить нашуlogger.debugЗаявление не печатается. Это потому, что нам пришлось изменить уровень журнала по умолчанию, чтобы сделать его видимым. когда мы создаемloggerнапример, мы устанавливаем значениеprocess.env.LOG_LEVELозначает, что мы можем изменить значение через него или принять значение по умолчаниюinfo. мы можем бежатьLOG_LEVEL=debug node index.jsдля настройки уровня журнала.
Прежде чем мы это сделаем, давайте проясним тот факт, что вывод прямо сейчас не очень читаем. Это сделано намеренно.pinoСледуя философии, для повышения производительности вы должны передавать (используя|) вывод перемещает любую обработку журнала в отдельный процесс. Это включает в себя создание его для чтения или загрузку на облачный хост. мы называем это传输. Проверятьо传输документацияпонятьpinoПочему ошибка не пишетсяstderr.
мы будем использоватьpino-prettyчтобы увидеть более удобочитаемую версию журнала. Запустите в терминале:
npm install --save-dev pino-pretty
LOG_LEVEL=debug node index.js | ./node_modules/.bin/pino-pretty
Теперь все ваши сообщения журнала будут использовать|вывод оператора наpino-prettyиди в. Если вы пойдете, чтобы спросить еще разhttp://localhost:3000. Вы все еще должны видеть свойdebugИнформация.
Существует множество существующих инструментов передачи, которые могут украсить или преобразовать ваши журналы. Вы даже можете пройтиpino-coladaдля отображения смайликов. Это будет полезно для вашего местного развития. После запуска сервера в производственной среде вы можете захотеть вывести журналы надругая передача,использовать>записать его на диск для последующей обработки или использовать что-то вродеteeкоманда для одновременной обработки.
ДолженДокументацияТакже будет содержать информацию о таких вещах, как чередование файлов журналов, фильтрация и запись журналов в разные файлы.
журнал вашей библиотеки
Теперь, когда мы рассмотрели, как эффективно писать журналы для серверных приложений, почему бы не использовать ту же технику для написанной нами библиотеки?
Проблема в том, что ваша библиотека может захотеть вести журнал для отладки, но она не должна загромождать приложение потребителя. И наоборот, потребители должны иметь возможность включить ведение журнала, если им нужно что-то отладить. Ваша библиотека по умолчанию не должна обрабатывать это и оставить запись для вывода пользователю.
expressхороший пример. существуетexpressВ рамках фреймворка происходит многое, и при отладке вашего приложения вам может понадобиться знать, что представляет собой фреймворк. если мы запросимexpressДокументация, вы заметите, что перед командой можно поставить префиксDEBUG=express:*Такая строка кода:
DEBUG=express:* node index.js
Если вы запустите эту команду с вашим текущим приложением, вы увидите много других выходных данных, которые могут помочь вам отладить проблему.
Если у вас не включено ведение журнала отладки, вы не увидите никаких таких журналов. Это делается путем вызоваdebugпакет для завершения. Это позволяет нам писать сообщения в «пространствах имен», если пользователь библиотеки включает пространство имен или в егоDEBUG переменная средыподстановочные знаки, соответствующие ему в , он выведет их. использоватьdebugбиблиотека, сначала установите ее:
npm install debug
Давайте смоделируем вызов нашей библиотеки, создав новый файлrandom-id.jsДавайте попробуем и напишем в нем такой код:
const debug = require('debug');
const log = debug('mylib:randomid');
log('Library loaded');
function getRandomId() {
log('Computing random ID');
const outcome = Math.random()
.toString(36)
.substr(2);
log('Random ID is "%s"', outcome);
return outcome;
}
module.exports = { getRandomId };
Это создаст пространство имен сmylib:randomidизdebugЗатем регистратор зарегистрирует оба сообщения. Тогда мы в предыдущем разделеindex.jsфайл с его использованием:
const express = require('express');
const pino = require('pino');
const expressPino = require('express-pino-logger');
const randomId = require('./random-id');
const logger = pino({ level: process.env.LOG_LEVEL || 'info' });
const expressLogger = expressPino({ logger });
const PORT = process.env.PORT || 3000;
const app = express();
app.use(expressLogger);
app.get('/', (req, res) => {
logger.debug('Calling res.send');
const id = randomId.getRandomId();
res.send(`Hello World [${id}]`);
});
app.listen(PORT, () => {
logger.info('Server running on port %d', PORT);
});
Если вы используете это времяDEBUG=mylib:randomid node index.jsперезапустить сервер, и он распечатает журнал отладки нашей «библиотеки».
Интересно, если пользователи вашей библиотеки захотят поместить эти методы отладочной информации в свои собственныеpinoжурналы, они могут использоватьpinoКоманда под названиемpino-debugбиблиотека для правильного форматирования этих журналов.
Используйте следующую команду для установки этой библиотеки:
npm install pino-debug
pino-debugЕго нужно инициализировать один раз, прежде чем мы используем его в первый раз.debug. Проще всего использовать перед запуском скриптаNode.js-rили--requireидентификатордля инициализации. Используйте следующую команду, чтобы перезапустить сервер (при условии, что вы установилиpino-colada):
DEBUG=mylib:randomid node -r pino-debug index.js | ./node_modules/.bin/pino-colada
Теперь вы можете просматривать журнал отладки библиотеки в том же формате, что и журнал приложения.
ваш вывод CLI
Последний случай, который я рассмотрю в этом сообщении блога, — это частный случай ведения журнала для CLI, а не для библиотеки. Моя философия состоит в том, чтобы отделить логические журналы от выходных «журналов» CLI. Для любого логического журнала вы должны использовать что-то вродеdebugбиблиотека. Это позволяет вам или другим лицам повторно использовать логику, не привязываясь к конкретному варианту использования CLI.
Когда вы создаете CLI с Node.js, вы можете сделать так, чтобы все выглядело красиво, добавив цвет, счетчики или отформатировав содержимое особым визуально привлекательным способом. Однако есть несколько ситуаций, которые следует учитывать при построении CLI.
Одним из случаев является то, что ваш CLI может использоваться в контексте системы непрерывного наследования (CI), поэтому вы можете захотеть удалить цвета или любой причудливый декоративный вывод. Некоторые системы CI устанавливают флаг среды под названием «CI». Если вы хотите безопаснее проверить, находитесь ли вы в CI, вы можете использовать пакет, который уже поддерживает несколько систем CI, например.is-ci.
Некоторые библиотеки, такие какchalkCI был обнаружен для вас и удалены цвета для вас. Давайте посмотрим, как это выглядит.
использоватьnpm install chalkустановитьchalk, и создайтеcli.jsдокумент. Поместите в него следующее:
const chalk = require('chalk');
console.log('%s Hi there', chalk.cyan('INFO'));
Теперь, если вы используетеnode cli.jsЗапустите этот скрипт, и вы увидите соответствующий цветной вывод.
но ты используешьCI=true node cli.jsчтобы запустить его, вы увидите, что цвета удалены:
Другой сценарий, который вы должны помнить, этоstdoutМожет работать в терминальном режиме. Означает запись содержимого в терминал. Если это так, мы можем использовать что-то вродеboxenчто-то, чтобы отобразить весь красивый вывод. В противном случае выходные данные могут быть перенаправлены в файл или переданы в другое место.
Ты можешь проверитьisTTYсоответствующие свойства потока для проверкиstdin,stdoutилиstderrНаходится в терминальном режиме. Например:process.stdout.isTTY, в этом случае используется специально для терминалов,TTYРасшифровывается как «телетайп».
В зависимости от того, как был запущен процесс Node.js, значение для каждого из трех потоков может быть разным. ты сможешьРаздел «Процесс ввода-вывода» документации Node.jsУзнайте больше об этом.
покажи намprocess.stdout.isTTYИзменение стоимости в различных ситуациях. обновить свойcli.jsфайл для проверки:
const chalk = require('chalk');
console.log(process.stdout.isTTY);
console.log('%s Hi there', chalk.cyan('INFO'));
затем используйтеnode cli.jsзапустите в своем терминале, вы увидитеtrueЗа ним последует наше красочное сообщение после печати.
После этого запустите то же самое, но перенаправьте вывод в файл, затем проверьте содержимое, запустив:
node cli.js > output.log
cat output.log
На этот раз вы увидите, что он напечатаетundefinedЗа ним следует простое бесцветное сообщение. так какstdoutрежим закрытого терминалаstdoutперенаправление. так какchalkиспользовалsupports-color, так что под капотом проверки наisTTY.
Однако, какchalkТакие инструменты уже обрабатывают это поведение за вас, и при разработке CLI вы всегда должны знать о ситуациях, когда ваш CLI может работать в режиме CI или вывод перенаправляется. Это также может помочь вам сделать шаг вперед в работе с CLI. Например, вы можете красиво упорядочить данные в терминале, еслиisTTYдаundefinedЕсли это так, переключитесь на более простой способ разбора.
Суммировать
Начните с JavaScript и используйтеconsole.logРегистрация вашей первой строки выполняется быстро, но вам следует больше думать о регистрации, когда вы запускаете свой код в производство. В этой статье описываются только различные доступные методы и решения для ведения журналов. Он не содержит всего, что вам нужно знать. Я предлагаю вам проверить некоторые из ваших любимых проектов с открытым исходным кодом, чтобы увидеть, как они решают проблемы ведения журналов и инструменты, которые они используют. Иди записывай все сейчас, не распечатывай свой журнал 😉
Если вы знаете или найдете какие-либо инструменты, которые я должен упомянуть явно, или если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь обращаться ко мне. Я не могу дождаться, чтобы увидеть, что вы делаете.
Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.