Специально к старту нового потока курса «Frontend-разработчик» делимся с вами полезным переводом. Автор рассказывает, как использует методы логирования в производственной среде собственного проекта и в чём именно они помогают. Кроме того, нас знакомят с платформой AppSignal, созданной, чтобы напрямую уведомлять разработчика о возникающих у пользователя исключениях в приложении. Подробности под катом.
![](https://habrastorage.org/r/w780q1/webt/zr/au/rw/zraurwarjorn3vrf--t7lx-r1ko.jpeg)
Я считаю себя инженером внутреннего программного обеспечения — и, как может подтвердить любой внутренний инженер, большая часть нашей жизни уходит на мониторинг, поиск и устранение неисправностей, а также отладку наших приложений. Фундаментальное правило разработки ПО: программное обеспечение будет давать сбои. Новых разработчиков от опытных отличает то, как они планируют эти сбои. Надежное и эффективное логирование — важная часть планирования на случай неудач и, в конечном счёте, смягчения их последствий. Как и в случае разработки бэкенда, логирование может быть полезно в разработке программного обеспечения фронтенда, но оно гораздо больше, чем просто поиск и устранение неисправностей и отладка. Эффективное фронтенд-логирование, кроме того, может сделать разработку продуктивной, быстрой и радостной.
Несмотря на то, что я разделяю и практикую разработку через тестирование, мне нравятся гибкость, богатство информации и надёжность кода, предоставляемые разработчикам фронтенда, которые эффективно используют
Советы по быстрому, грязному логированию разработки с
.
Да, правда. Я не пользуюсь
![](https://habrastorage.org/r/w1560/webt/dc/0k/k_/dc0kk_lssuc8e9djmtopqn_igwq.png)
Это просто — используйте синтаксис вычисляемых свойств ES6: оберните объекты, которые вы хотите логировать, в фигурные скобки вот так:
![](https://habrastorage.org/r/w1560/webt/8b/6p/4d/8b6p4dlz7hbcmd_eekezh5nawta.png)
Отображение уровней логирования:
![](https://habrastorage.org/r/w1560/webt/db/aw/rr/dbawrrjkbof5ip0cvjyuoubutjq.png)
![](https://habrastorage.org/webt/s4/uw/gz/s4uwgziwcwl_b_oqdmluw9gwekq.gif)
При логировании списков элементов пользуйтесь
Одна из моих любимых функций говорит сама за себя. Если вам когда-нибудь понадобится логировать список объектов, дайте шанс
![](https://habrastorage.org/r/w1560/webt/-n/x6/yc/-nx6ycfvh7xlijo_vdhuc850-uw.png)
Дебажим быстро с помощью
Хотите сэкономить несколько драгоценных секунд? Вместо того чтобы искать файл в консоли разработчика, в который хотите добавить точку останова, впишите в код строку
![](https://habrastorage.org/r/w1560/webt/s6/hv/gr/s6hvgrzqdx6azwtkwubgxmudf84.png)
![](https://habrastorage.org/r/w1560/webt/kq/ax/ms/kqaxmsussqe62bzyfrjlk3ycf_m.png)
Тонкое профилирование с
Хотите профилировать поток пользователя в вашем приложении, чтобы найти горячие точки? Укажите триггер
![](https://habrastorage.org/r/w780q1/webt/-m/n7/ge/-mn7gem8df2ppwg2kymq_7avdvk.jpeg)
![](https://habrastorage.org/webt/i9/pg/zq/i9pgzqmadyrqqzctaxus641obhy.gif)
Кроме того, можно точно измерить, сколько времени занимает выполнение потока, поместив
![](https://habrastorage.org/r/w1560/webt/2i/qy/ul/2iqyuljjvybtkiksu50ukvxwgvk.png)
Подсчёт количества выполнений кода через
Это одна из тех функций, для которых я не нашёл особого применения, тем не менее польза от нее есть:
![](https://habrastorage.org/r/w1560/webt/-u/sm/df/-usmdfy8zvbclrjslxwtf9mugti.png)
Безусловно, это моя любимая консольная функция, которую я широко использую при логировании в производственной среде (подробнее об этом — в соответствующем разделе). Ближе к сути: мы можем использовать строки форматирования, чтобы форматировать сообщения лога. Здесь
![](https://habrastorage.org/r/w1560/webt/hm/vr/vd/hmvrvd0oavdmeverod9r46_hcru.png)
Можно стилизовать несколько элементов, расширив строку через
![](https://habrastorage.org/r/w1560/webt/np/w4/tn/npw4tnmgnuhu77kwstkaijvra4o.png)
Я выраженный визуал, мне нравится тратить какое-то время на то, чтобы информационные и отладочные логи выглядели красиво и в то же время были полезны. Я широко использую эту функцию в производственном логировании Firecode.io. И это прекрасная тема для следующего раздела.
![](https://habrastorage.org/r/w780q1/webt/sb/lr/2c/sblr2czbuuwokmraou2y8krymk0.jpeg)
Логирование через
.
Подготовка кода фронтенда включает несколько этапов. Некоторые из них — это уменьшение размера и сжатие вашего кода, генерация дайджестов кэшируемых ассетов и удаление
Но когда приложение используете вы, скорее всего, вы хотите добиться тонкого логирования, чтобы понимать, как ваше приложение работает, а также находить и устранять ошибки. Если ваше приложение используется другими людьми, хочется получать уведомления, когда они сталкиваются с ошибками, чтобы проследить их в коде и исправить их. Вот, что делаю в этом случае я.
Вместо этого я написал обёртку, которая содержит логику условного логирования, основанную на уровне логирования, который, в свою очередь, основывается на глобальной переменной бэкенда.
Внимание! Впереди фрагменты кода TypeScript. Если вы не знакомы с TypeScript, думайте о нём, как о надмножестве JavaScript с типами, на которых сделан акцент (это грубое упрощение). Иначе говоря,
Разрабатывая Firecode.io, я написал собственный фронтенд-фреймворк, который использует RxJS, но содержит знакомые концепции, такие как компоненты, из других популярных фреймворков, к примеру, React и Vue. При этом добавлены и другие концепции: движки для блоков тяжёлого для процессора кода, каналы для сообщений WebSocket и клиенты для HTTP-запросов. Очень важна была визуализация совместной работы всех этих частей, поэтому я реализовал пользовательское форматирование в классе-обёртке
![](https://habrastorage.org/r/w1560/webt/rb/r8/e5/rbr8e5zcgj4dkano3gqqli7mqgy.png)
Вместо вызова
![](https://habrastorage.org/r/w1560/webt/va/eb/rt/vaebrtumlpzu9jkwdb2az1hutt0.png)
Так я во время разработки визуально концентрируюсь на компонентах приложения. Например, когда я хочу посмотреть, что делает
Я настроил Firecode.io на включение логирования на уровне отладки по умолчанию для пользователей-администраторов через переменную JavaScript, она устанавливается бэкендом. При этом предприимчивые пользователи все еще могут найти и установить соответствующие флаги в консоли разработчика, чтобы включить точный журнал. Это лучше, чем ситуация, когда каждому пользователю приложения по умолчанию представлены все логи, и лучше, чем постпроцессор, полностью удаляющий логи из приложения в производственной среде. Установка уровня логирования на бэкенде в Ruby on Rails:
И в классе
И последнее, но не менее важное: хочется получать уведомления, когда пользователи сталкиваются с исключениями в приложении, не обязательно при этом с выводом на консоль разработчика. Это возможно. Включите вызов, передающий ваши ошибки в APM-сервис стороннего вендора (например AppSignal) в функцию ошибок вашего логгера. Пример:
AppSignal содержит интеграции для передачи ваших ошибок в службы исходящих уведомлений, таких как Slack, PagerDuty и OpsGenie, — вы даже можете подключить инструмент управления проектами, например JIRA или Trello, чтобы автоматически создавать Issues и баги для удобства вашей команды.
Я очень надеюсь, что эти советы и истории сделают вашу фронтенд-разработку немного продуктивнее и веселее! Очевидно, что в этом посте я коснулся только поверхности боевого искусства логирования, так что, если у вас есть еще какие-то советы, которыми можно поделиться, я бы с удовольствием прочитал их в своём Twitter.
![](https://habrastorage.org/r/w780q1/webt/oi/u1/9m/oiu19mtehaqclcqv-ys_t_px4cw.jpeg)
И два дополнения. Я перестраиваю Firecode.io с нуля, добавляя совершенно новый набор вопросов для собеседований по кодированию JavaScript, Java, Python и Scala.
Если вы заинтересованы в написании кода для подготовки к собеседованию, который адаптируется к вашему стилю обучения и доставляет удовольствие, зарегистрируйтесь, указав свой адрес электронной почты здесь. При запуске нового Firecode.io я предоставлю вам бесплатную трёхмесячную подписку. Я буду размещать больше материалов о создании веб-приложений промышленного масштаба (таких как Firecode.io) с нуля в качестве стороннего проекта. Если вы новичок в JavaScript и хотите понять, как объектноориентированный JavaScript и прототипное наследование работают под капотом, ознакомьтесь с моей любимой книгой по этой теме — The Principles of Object-Oriented JavaScript, и, если вам интересно узнать больше о том, почему вместо JS следует использовать TypeScript, ознакомьтесь с Effective TypeScript.
А помимо специальной литературы вам поможет промокод HABR, добавляющий 10 % к скидке на баннере.
![image](https://habrastorage.org/r/w780q1/webt/3l/jl/dd/3ljlddfcnkh0nu0n75e6v4q8i4u.jpeg)
![](https://habrastorage.org/webt/zr/au/rw/zraurwarjorn3vrf--t7lx-r1ko.jpeg)
Я считаю себя инженером внутреннего программного обеспечения — и, как может подтвердить любой внутренний инженер, большая часть нашей жизни уходит на мониторинг, поиск и устранение неисправностей, а также отладку наших приложений. Фундаментальное правило разработки ПО: программное обеспечение будет давать сбои. Новых разработчиков от опытных отличает то, как они планируют эти сбои. Надежное и эффективное логирование — важная часть планирования на случай неудач и, в конечном счёте, смягчения их последствий. Как и в случае разработки бэкенда, логирование может быть полезно в разработке программного обеспечения фронтенда, но оно гораздо больше, чем просто поиск и устранение неисправностей и отладка. Эффективное фронтенд-логирование, кроме того, может сделать разработку продуктивной, быстрой и радостной.
Несмотря на то, что я разделяю и практикую разработку через тестирование, мне нравятся гибкость, богатство информации и надёжность кода, предоставляемые разработчикам фронтенда, которые эффективно используют
console.log()
. Я решил поделиться некоторыми советами и хитростями, которые изучил и включил в свой рабочий процесс во время работы над Firecode.io в надежде, что некоторые из них помогут сделать ваш рабочий процесс разработки немного продуктивнее и веселее. С удовольствием разделю эти советы на две широкие категории: быстрое и грязное логирование, когда вы активно собираете и отлаживаете приложение, и долговременная запись в лог для понимания, когда ваше приложение работает, как ожидалось, а когда нет.Советы по быстрому, грязному логированию разработки с console.log()
.Не используйте console.log()
.Да, правда. Я не пользуюсь
console.log()
. Хотя… Ладно. Я пишу обёртки, которые используют console.log
. Подробнее об этом — в разделе логирования в производственной среде. Но, если вы хотите логировать что-то в приложении, чтобы увидеть, что происходит, используйте console.trace()
. В дополнение ко всему из console.log()
этот метод выводит всю трассировку стека, чтобы вы точно знали, откуда идёт сообщение.![](https://habrastorage.org/webt/dc/0k/k_/dc0kk_lssuc8e9djmtopqn_igwq.png)
Используйте имена вычисляемых свойств ES6 для идентификации объектов и чтобы не путать их с именами переменных.
Это просто — используйте синтаксис вычисляемых свойств ES6: оберните объекты, которые вы хотите логировать, в фигурные скобки вот так:
console.log({user})
, а не console.log(user)
. Логирование аккуратное: ключ — имя переменной, а значение — сам объект. Такой подход особенно полезен, когда вы спешите и хотите логировать несколько объектов одной командой console.log()
.![](https://habrastorage.org/webt/8b/6p/4d/8b6p4dlz7hbcmd_eekezh5nawta.png)
Отображение уровней логирования: ERROR, WARN, INFO
console.log(param)
по умолчанию имеет значение INFO
— однако в вашем распоряжении 3 других уровня логирования, которыми вы не должны пренебрегать — console.debug()
, console.warning()
и console.error()
. Помимо различий в форматировании (заметили разные цвета?) консоль разработчика в браузере позволяет легко отфильтровывать логи разных уровней с помощью удобного выпадающего списка, ненужные логи убираются вот так:![](https://habrastorage.org/webt/db/aw/rr/dbawrrjkbof5ip0cvjyuoubutjq.png)
![](https://habrastorage.org/webt/s4/uw/gz/s4uwgziwcwl_b_oqdmluw9gwekq.gif)
При логировании списков элементов пользуйтесь console.table()
Одна из моих любимых функций говорит сама за себя. Если вам когда-нибудь понадобится логировать список объектов, дайте шанс
console.table()
.![](https://habrastorage.org/webt/-n/x6/yc/-nx6ycfvh7xlijo_vdhuc850-uw.png)
Дебажим быстро с помощью debugger
Хотите сэкономить несколько драгоценных секунд? Вместо того чтобы искать файл в консоли разработчика, в который хотите добавить точку останова, впишите в код строку
debugger
эта строка остановит выполнение кода. Это всё, теперь можно отлаживать и переходить к функциям, как обычно.![](https://habrastorage.org/webt/s6/hv/gr/s6hvgrzqdx6azwtkwubgxmudf84.png)
![](https://habrastorage.org/webt/kq/ax/ms/kqaxmsussqe62bzyfrjlk3ycf_m.png)
Тонкое профилирование с console.profile()
и console.time()
Хотите профилировать поток пользователя в вашем приложении, чтобы найти горячие точки? Укажите триггер
console.profile(profileName)
в начале профилируемого кода и console.profileEnd(profileName)
в его конце, чтобы исследовать профиль процессора в потоке.![](https://habrastorage.org/webt/-m/n7/ge/-mn7gem8df2ppwg2kymq_7avdvk.jpeg)
![](https://habrastorage.org/webt/i9/pg/zq/i9pgzqmadyrqqzctaxus641obhy.gif)
Кроме того, можно точно измерить, сколько времени занимает выполнение потока, поместив
console.time(id)
в его начале и console.timeEnd(id)
в его конце.![](https://habrastorage.org/webt/2i/qy/ul/2iqyuljjvybtkiksu50ukvxwgvk.png)
Подсчёт количества выполнений кода через console.count()
Это одна из тех функций, для которых я не нашёл особого применения, тем не менее польза от нее есть:
console.count(label)
помогает точно узнать, сколько раз выполняется фрагмент кода, это полезно при поиске и устранении состояния гонки и в других ситуациях.![](https://habrastorage.org/webt/-u/sm/df/-usmdfy8zvbclrjslxwtf9mugti.png)
Красивое логирование с помощью CSS
Безусловно, это моя любимая консольная функция, которую я широко использую при логировании в производственной среде (подробнее об этом — в соответствующем разделе). Ближе к сути: мы можем использовать строки форматирования, чтобы форматировать сообщения лога. Здесь
%c
— модификатор для кода CSS, а всё, что после него, — это сообщение.![](https://habrastorage.org/webt/hm/vr/vd/hmvrvd0oavdmeverod9r46_hcru.png)
Можно стилизовать несколько элементов, расширив строку через
%s
, вот так:![](https://habrastorage.org/webt/np/w4/tn/npw4tnmgnuhu77kwstkaijvra4o.png)
Я выраженный визуал, мне нравится тратить какое-то время на то, чтобы информационные и отладочные логи выглядели красиво и в то же время были полезны. Я широко использую эту функцию в производственном логировании Firecode.io. И это прекрасная тема для следующего раздела.
![](https://habrastorage.org/webt/sb/lr/2c/sblr2czbuuwokmraou2y8krymk0.jpeg)
Логирование через console.log()
в производственной среде
.Подготовка кода фронтенда включает несколько этапов. Некоторые из них — это уменьшение размера и сжатие вашего кода, генерация дайджестов кэшируемых ассетов и удаление
console.log()
из кода приложения. Почему удаляется console.log()
? Потому что не хочется, чтобы пользователи открывали консоль разработчика и видели логи — дыры в безопасности для пытливых умов. Но когда приложение используете вы, скорее всего, вы хотите добиться тонкого логирования, чтобы понимать, как ваше приложение работает, а также находить и устранять ошибки. Если ваше приложение используется другими людьми, хочется получать уведомления, когда они сталкиваются с ошибками, чтобы проследить их в коде и исправить их. Вот, что делаю в этом случае я.
Не пользуюсь console.log()
Вместо этого я написал обёртку, которая содержит логику условного логирования, основанную на уровне логирования, который, в свою очередь, основывается на глобальной переменной бэкенда.
Внимание! Впереди фрагменты кода TypeScript. Если вы не знакомы с TypeScript, думайте о нём, как о надмножестве JavaScript с типами, на которых сделан акцент (это грубое упрощение). Иначе говоря,
const str = "some string";
превращается в const str: string = "some string"
— типы добавляются после имени переменной с двоеточием.Разрабатывая Firecode.io, я написал собственный фронтенд-фреймворк, который использует RxJS, но содержит знакомые концепции, такие как компоненты, из других популярных фреймворков, к примеру, React и Vue. При этом добавлены и другие концепции: движки для блоков тяжёлого для процессора кода, каналы для сообщений WebSocket и клиенты для HTTP-запросов. Очень важна была визуализация совместной работы всех этих частей, поэтому я реализовал пользовательское форматирование в классе-обёртке
Logger
, этот класс форматирует и визуально отделяет журналы от каждой части приложения.![](https://habrastorage.org/webt/rb/r8/e5/rbr8e5zcgj4dkano3gqqli7mqgy.png)
Вместо вызова
console.log("Cache SET to", {value})
я вызываю Logger.debug("Cache set to", {value}, Framework.Cache)
. В классе Logger
есть перечисление TypeScript, сопоставляющее каждый компонент фреймворка с цветом:![](https://habrastorage.org/webt/va/eb/rt/vaebrtumlpzu9jkwdb2az1hutt0.png)
Так я во время разработки визуально концентрируюсь на компонентах приложения. Например, когда я хочу посмотреть, что делает
WsRequestCache
, я могу «отключиться» от всех логов, кроме бирюзовых.Защитите логи установкой уровня логирования на бэкенде
Я настроил Firecode.io на включение логирования на уровне отладки по умолчанию для пользователей-администраторов через переменную JavaScript, она устанавливается бэкендом. При этом предприимчивые пользователи все еще могут найти и установить соответствующие флаги в консоли разработчика, чтобы включить точный журнал. Это лучше, чем ситуация, когда каждому пользователю приложения по умолчанию представлены все логи, и лучше, чем постпроцессор, полностью удаляющий логи из приложения в производственной среде. Установка уровня логирования на бэкенде в Ruby on Rails:
const logLevel: number = <%= @app.get_log_level_for_user %>
И в классе
Logger
: class Logger {
...
...
static info(...) {
shouldLog(Level.INFO) && console.log(...);
...
}
}
Логируйте возможные ошибки и уведомляйте о них
И последнее, но не менее важное: хочется получать уведомления, когда пользователи сталкиваются с исключениями в приложении, не обязательно при этом с выводом на консоль разработчика. Это возможно. Включите вызов, передающий ваши ошибки в APM-сервис стороннего вендора (например AppSignal) в функцию ошибок вашего логгера. Пример:
class Logger {
...
...
static error(e) {
if (shouldLog(Level.ERROR)) {
console.error(e);
}
appsignal.sendError(e);
}
}
AppSignal содержит интеграции для передачи ваших ошибок в службы исходящих уведомлений, таких как Slack, PagerDuty и OpsGenie, — вы даже можете подключить инструмент управления проектами, например JIRA или Trello, чтобы автоматически создавать Issues и баги для удобства вашей команды.
Итоги
Я очень надеюсь, что эти советы и истории сделают вашу фронтенд-разработку немного продуктивнее и веселее! Очевидно, что в этом посте я коснулся только поверхности боевого искусства логирования, так что, если у вас есть еще какие-то советы, которыми можно поделиться, я бы с удовольствием прочитал их в своём Twitter.
![](https://habrastorage.org/webt/oi/u1/9m/oiu19mtehaqclcqv-ys_t_px4cw.jpeg)
И два дополнения. Я перестраиваю Firecode.io с нуля, добавляя совершенно новый набор вопросов для собеседований по кодированию JavaScript, Java, Python и Scala.
Если вы заинтересованы в написании кода для подготовки к собеседованию, который адаптируется к вашему стилю обучения и доставляет удовольствие, зарегистрируйтесь, указав свой адрес электронной почты здесь. При запуске нового Firecode.io я предоставлю вам бесплатную трёхмесячную подписку. Я буду размещать больше материалов о создании веб-приложений промышленного масштаба (таких как Firecode.io) с нуля в качестве стороннего проекта. Если вы новичок в JavaScript и хотите понять, как объектноориентированный JavaScript и прототипное наследование работают под капотом, ознакомьтесь с моей любимой книгой по этой теме — The Principles of Object-Oriented JavaScript, и, если вам интересно узнать больше о том, почему вместо JS следует использовать TypeScript, ознакомьтесь с Effective TypeScript.
А помимо специальной литературы вам поможет промокод HABR, добавляющий 10 % к скидке на баннере.
![image](https://habrastorage.org/webt/3l/jl/dd/3ljlddfcnkh0nu0n75e6v4q8i4u.jpeg)
- Обучение профессии Data Science
- Обучение профессии Data Analyst
- Онлайн-буткемп по Data Analytics
- Курс «Python для веб-разработки»
Eще курсы
- Продвинутый курс «Machine Learning Pro + Deep Learning»
- Курс «Математика и Machine Learning для Data Science»
- Курс по Machine Learning
- Разработчик игр на Unity
- Курс по JavaScript
- Профессия Веб-разработчик
- Профессия Java-разработчик
- C++ разработчик
- Курс по аналитике данных
- Курс по DevOps
- Профессия iOS-разработчик с нуля
- Профессия Android-разработчик с нуля