Диагностика, которой можно поделиться: генерация HTML-отчётов из профилирования в продакшене

Материал основан на разборе dev.to. Ниже — главное и практические шаги, которые можно быстро применить в работе.


Использование HTML-отчетов может быть значительно улучшено в контексте обработки данных и отчетности. Например, связанный материал о "отчетах и обработках в 1С" может помочь вам глубже понять, как строить отчеты в программных системах. Вы можете прочитать больше здесь.

Почему вывод в терминал не работает для команды

Вы определили проблему с производительностью в продакшене: processPayload в /app/handlers/payment.js:127 использовал 54% времени процессора, три HTTP-вызова к платёжному шлюзу в среднем занимали 1,8 секунды, а event loop задерживался 12 раз за 30-секундный захват.

Теперь необходимо поделиться этой информацией с командой. Вы копируете вывод терминала в Slack, но ANSI-коды цветов превращаются в непонятные символы, и столбчатые диаграммы становятся нечитаемыми.

Именно поэтому в node-loop-detective v2.0.0 появился вывод HTML-отчётов.

loop-detective 12345 --html report.html

Один флаг. Один файл. Откройте в любом браузере. Поделитесь где угодно.

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

Он плохо передаётся. ANSI escape-коды отображаются как [31m в Slack, email, Jira и большинстве текстовых редакторов. Всё форматирование теряется.

Он не интерактивен. Вы не можете свернуть стек вызовов, который вас не интересует. Нельзя навести курсор на событие задержки, чтобы увидеть его временную метку, или отсортировать таблицу функций по процентам.

Он эфемерен. Как только терминал прокрутился дальше — всё пропало. Можно перенаправить вывод в файл, но тогда у вас будет обычный текстовый файл с escape-кодами.

Вывод в формате JSON (--json) сохраняет данные, но затрудняет их восприятие. Чтение крупных JSON-файлов на 500 строк в Slack не будет комфортным. HTML-отчёт, в свою очередь, решает обе задачи.

Как выглядит HTML-отчёт

Отчёт — это единственный самодостаточный HTML-файл с тёмной темой, вдохновлённой интерфейсом GitHub. Никаких внешних CSS, никаких ссылок на JavaScript CDN, никаких загружаемых изображений. Он работает офлайн, работает на любом устройстве и весит около 15–20 КБ для типичного отчёта.

В нём шесть секций.

Сводные карточки

Верхние пять карточек представляют ключевые показатели: продолжительность профилирования, количество сэмплов CPU, количество активно используемых функций, количество событий задержки и число медленных операций ввода-вывода. За одну секунду можно оценить, насколько этот отчёт вам интересен.

Диагностика

Каждый выявленный паттерн отображается с цветным индикатором уровня критичности (HIGH — красный, MED — жёлтый, LOW — зелёный), описанием, местом в коде и рекомендациями по исправлению. Это те же данные, что представлены в терминальном выводе, но отформатированные для удобного восприятия.

Таблица CPU-нагруженных функций

В таблице отображаются визуальные полосы, показывающие процент загрузки. Полосы цветокодированы: красный для более 50% использования CPU, жёлтый для более 20%, зелёный для остальных. Каждая строка включает имя функции, визуальную полосу, время в миллисекундах и местоположение файла.

Сворачиваемые стеки вызовов

Для самых затратных функций доступны раскрываемые стеки вызовов. Кликните для развертывания, снова нажмите для сворачивания. Это делает отчёт компактным, при этом полная детализация доступна по запросу. Целевая функция выделена жёлтым цветом.

Сводка медленного ввода-вывода

Сгруппировано по типу (HTTP, FETCH, DNS, TCP), затем по цели. Каждая группа показывает количество вызовов, общую продолжительность, среднее и максимальное значение. Трассировки стека вызывающей стороны показаны встроенно. Количество ошибок отмечается красным значком.

Временная шкала задержек event loop

Визуальная временная шкала событий задержки, представленных в виде цветных точек. Размер точки масштабируется в зависимости от серьёзности задержки. Наведите курсор на любую точку, чтобы увидеть точную продолжительность задержки и временную метку. Под временной шкалой таблица агрегирует события задержки по местоположению в коде.

Проектные решения: почему именно так

Почему самодостаточный файл?

Отчёт должен работать при прикреплении к тикету Jira, отправке коллеге по email или открытии через шесть месяцев во время разбора инцидента. Внешние зависимости — CSS, размещённый на CDN, JavaScript-библиотеки, веб-шрифты — ломаются во всех этих сценариях. Корпоративные файрволы блокируют CDN. Офлайн-доступ не работает. Ссылки устаревают.

Каждый байт CSS и JavaScript встроен прямо в HTML-файл. Можно положить его на USB-накопитель — и он будет работать.

Почему тёмная тема?

Разработчики проводят свои дни, глядя на редакторы и терминалы с тёмной темой. Ярко-белый отчёт режет глаза. Тёмная тема, вдохновлённая GitHub (фон #0d1117, текст #c9d1d9), органично вписывается в рабочий процесс разработчика.

Почему сворачиваемые стеки вызовов?

Отчёт с пятью развёрнутыми стеками вызовов, каждый глубиной 10–15 фреймов, подавляет. В большинстве случаев вас интересует только один или два стека. Сворачиваемые секции позволяют быстро просмотреть цели и развернуть только то, что актуально.

Реализация на ванильном JavaScript — никакого фреймворка, никакого шага сборки.

Почему не полноценный дашборд?

Мы рассматривали возможность генерации отчёта с графиками: линейные графики для задержки во времени, круговые диаграммы для распределения CPU. Но графики требуют библиотеки для построения (Chart.js, D3 и т.д.), что либо раздует файл, либо потребует CDN. Текущий подход — цветные полосы, точки разного размера, таблицы — передаёт ту же информацию с помощью чистого HTML и CSS.

Если вам нужны графики, используйте --json и передайте данные в предпочитаемый инструмент визуализации.

Как это работает внутри

Генератор HTML-отчётов (src/html-report.js) — это чистая функция, которая принимает данные анализа и возвращает HTML-строку:

function generateHtmlReport(data) { const { analysis, lagEvents, slowIOEvents, config, timestamp } = data; return `<!DOCTYPE html>
<html> <head> <style>/* весь CSS встроен */</style> </head> <body> ${renderSummary(analysis.summary, lagEvents, slowIOEvents)} ${renderPatterns(analysis.blockingPatterns)} ${renderHeavyFunctions(analysis.heavyFunctions)} ${renderCallStacks(analysis.callStacks)} ${renderSlowIO(slowIOEvents)} ${renderLagEvents(lagEvents)} <script>/* переключение сворачивания */</script> </body>
</html>`;
}

Каждая секция рендерится отдельной функцией. Все строки, предоставленные пользователем (имена функций, пути к файлам, сообщения об ошибках), экранируются HTML для предотвращения XSS (межсайтового скриптинга) — даже несмотря на то, что отчёт генерируется локально, это хорошая практика.

В CLI события захватываются до того, как репортер их очищает.

Комбинирование форматов вывода

HTML-отчёт работает совместно со всеми другими параметрами вывода:

# Вывод в терминал + HTML-отчёт
# Терминал + HTML + CPU-профиль для flame graph
loop-detective 12345 -d 60 --html report.html --save-profile profile.cpuprofile
# JSON + HTML (JSON идёт в stdout, HTML в файл)
loop-detective 12345 --json --html report.html > data.json

Каждый формат служит своей цели:

Терминал — немедленная диагностика, пока вы за клавиатурой

HTML — обмен с командой, прикрепление к тикетам, архивирование

JSON — передача в системы мониторинга, пользовательские скрипты анализа

.cpuprofile — глубокий визуальный анализ в Chrome DevTools или speedscope

Я использую комбинацию --html и --json как стандартный набор при любом инциденте: HTML уходит в документ разбора, JSON — в систему мониторинга для агрегации. Мой совет — запускать оба флага по умолчанию, не задумываясь: лишний файл не мешает, а нужный оказывается под рукой. На нашем опыте именно HTML-отчёт чаще всего открывают коллеги, которые не были за клавиатурой в момент инцидента.

Реальные сценарии применения

Разборы инцидентов

Во время инцидента запустите loop-detective с --html:

loop-detective 12345 -d 60 --html incident-2025-03-15.html

Прикрепите HTML-файл к документу разбора инцидента. Через шесть месяцев любой сможет открыть его и увидеть, что именно происходило: какие функции были горячими, какой ввод-вывод был медленным, когда происходили события задержки.

Доказательства при ревью кода

Обнаружили регрессию производительности? Профилируйте старую и новую версии, сгенерируйте HTML-отчёты для обеих и прикрепите их к pull request (запросу на слияние). Ревьюер может открыть оба файла рядом и сравнить — без необходимости воспроизводить окружение локально.

Автоматизированная отчётность

В CI/CD-пайплайне или запланированном задании:

loop-detective --port 9229 -d 30 \ --html /reports/daily-$(date +%Y%m%d).html \ --json > /reports/daily-$(date +%Y%m%d).json

Поднимите простой файловый сервер над директорией с отчётами — и у вас будет дашборд истории производительности без единой строки дополнительного кода.

Как начать

npm install -g node-loop-detective@2.0.0
loop-detective <pid> --html report.html

Откройте report.html в браузере. Поделитесь с командой. Прикрепите к тикету. Диагностические данные больше не заперты в вашем терминале.

Ответы на эти вопросы могут быть для вас полезными

Работает ли HTML-отчёт без интернета? Да. Все CSS и JavaScript встроены прямо в файл. Отчёт открывается в браузере без каких-либо внешних запросов — это принципиальное проектное решение.

Можно ли использовать HTML-отчёт и JSON-вывод одновременно? Можно. Флаги не конфликтуют: --json пишет данные в stdout, --html сохраняет файл. Оба формата генерируются за один запуск профилирования.

Насколько большим получается HTML-файл? Для типичного 30–60-секундного профилирования — около 15–20 КБ. Это меньше большинства изображений и без проблем прикрепляется к тикетам или письмам.

Как защититься от XSS в отчёте, если данные приходят из продакшена? Генератор экранирует все пользовательские строки — имена функций, пути к файлам, сообщения об ошибках — перед вставкой в HTML. Даже если в имени функции окажется вредоносный фрагмент, он отобразится как текст, а не выполнится.

Можно ли генерировать HTML-отчёты программно, без CLI? Да. Функция generateHtmlReport экспортируется из src/html-report.js и принимает объект с данными анализа. Это позволяет встраивать генерацию отчётов в собственный инструментарий или CI-скрипты.

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x