- Зачем:
- второй круг ревью нашёл, что текст спорит с собственной приёмкой: окно
держалось доводом «слияния за минуту-две», а замер даёт двадцать секунд;
довод панели ошибок опирался на отказ по памяти, которого ADR 0004 на этом
стенде не обещает.
- Что:
- «Части» сортируются по таблице: сортировка по числу частей разводила две
ноды одной таблицы, как только между ними вставала чужая.
- у «Слияний» столбик шириной в минуту, иначе редкие события выходили
волосяной линией; из заголовка убран «слой» — фильтр отсекает журналы
сервера, а не выбирает слои.
- в cluster.md исправлены довод за окно, ложное «времени в system.parts нет»,
счёт панелей без нод (их две, не одна) и разрешение, в котором снят замер
процессора.
- панель ошибок и её запись в ADR 0002 переписаны под проверенное: отказ на
шарде воспроизведён принудительным пределом памяти.
- из queries.md убран абзац про SELECT 1 — он объяснял пол удалённой панели.
- Проверка:
- make config-test; make smoke 21/21; make check-clickhouse 10/10.
- все десять панелей отвечают через /api/ds/query в окнах на полчаса, час и
шесть часов; шаг столбика слияний проверен отдельным запросом.
12 KiB
ADR 0002. Что показывает мониторинг стенда
Дата: 31 июля 2026 года. Статус: принято.
Решение
Мониторинг стенда — несколько дашбордов Grafana, по одному на вопрос. Дашборд, отвечающий на три вопроса сразу, не отвечает ни на один; отдельных файлов не жалко.
«Данные» — главный дашборд, вопросы дата-инженера:
- свежесть: сколько прошло с момента, когда доехало последнее событие;
- поток: строк в час по источникам и как это выглядит против вчерашнего;
- брак: сколько записей ушло в таблицы
*_errorsи какая это доля; - сходимость: сколько произвели в Kafka против того, сколько приземлилось в ClickHouse;
- отставание чтения из Kafka;
- дневной слепок заказов: доехал ли и вовремя ли.
Источник большинства этих панелей — не Prometheus, а сам ClickHouse: он подключается в Grafana источником данных, панели пишутся на SQL. Метрики дата-инженера живут в его собственных таблицах, а не в счётчиках сервисов.
«Кластер» — состояние машины: процессор и память обеих нод, обращения к
дискам, части MergeTree и слияния, keeper, очередь распределённых DDL. Дашборд
кажется чужим для дата-инженера, но чужой он только на вид: «слишком много
частей» — это ошибка того, кто вставляет мелкими пачками слишком часто, а
видна она именно здесь. То же с памятью: тяжёлый GROUP BY без ограничения —
запрос человека, симптом — на графике памяти.
Смотреть этот дашборд осмысленно под нагрузкой: видно, как процессор и обращения к дискам лезут вверх на вставке и медленно оседают, когда домержились части. Одно число «жив или нет» этому не учит, форма кривой — учит.
«Запросы» — system.query_log таблицей: что выполнялось, сколько заняло,
сколько памяти и строк прочитало. Здесь человек сам отвечает себе на вопрос
«почему мой дашборд в Superset тормозит».
Системные таблицы у каждой ноды свои, поэтому панели по ним пишутся через
clusterAllReplicas — иначе видно половину правды. Это отдельный маленький
урок, и он нужен.
Серверный журнал (system.text_log) подключается на этапе 9 вместе с runbook
«keeper упал / DDL повис в очереди»: там он и окупается. Довод за него один —
общая ось времени: в одной панели оба узла, над ней всплеск процессора, под
ней очередь DDL. docker logs даёт две отдельные ленты и сопоставление
руками. Издержки: журнал выключен по умолчанию, включается настройкой, таблице
нужен TTL. Если окажется дороже, чем даёт, — уходит первым.
Prometheus остаётся, но сжимается до тонкого пола: живы ли контейнеры, не упёрлись ли ноды в память. Он нужен, чтобы при плохой метрике данных одним взглядом отделить «сломался конвейер» от «сломалась машина». Отдельный сборщик метрик Kafka нужен ради отставания чтения. Сборщик метрик Airflow через StatsD не берём.
Почему
Образцом служил мониторинг предшественника: четыре дашборда, десять правил оповещения, два внешних сборщика и урок курса. Форма там хорошая и берётся целиком — сначала смотрим, потом ломаем одну вещь управляемым образом, видим, как мониторинг это показал, и возвращаем назад. Содержание берётся не целиком.
Панелей с запросами в трёх «настоящих» дашбордах предшественника — 28. На вопрос «с данными всё в порядке?» отвечают шесть. Остальное — процессор, память, части и слияния, размер набора DAG-файлов, время их разбора, пульс планировщика, свободные слоты исполнителя. И при этом ни одной панели про свежесть, ни одной про долю брака, ни одной про сходимость Kafka с ClickHouse. То есть три главных вопроса дата-инженера там просто не заданы.
Отсюда решение: инфраструктурные панели не убираются, а переносятся на свой дашборд, и рядом появляется тот, которого не было.
Три вещи предшественника не повторяем.
Правило оповещения Kafka No Messages Produced краснеет на здоровом стенде,
когда живой поток просто не запущен, и уроку приходится за это извиняться
отдельным абзацем. Правило, красное в нормальном состоянии, учит не тому, что
задумано: оно учит не смотреть на оповещения.
Самый проработанный дашборд предшественника — про генератор, которого в бою не существует: 17 панелей с гистограммами задержек и пульсом против 12 у ClickHouse. Силы ушли туда, где инструментировать было легко, а не туда, где стоит вопрос.
Три текстовые панели там хранят команды и пометку «настроено под тик 5 секунд» прямо в JSON дашборда. Поменяется тик — панель молча соврёт. Документация живёт в документации.
Сборщик метрик Airflow через StatsD — это отдельный контейнер плюс файл перевода имён, и весь его выход — внутренности планировщика: пульс, слоты, время разбора файлов. Дежурному по платформе это нужно, дата-инженеру — нет. Вопрос «доехал ли вчерашний слепок заказов» дешевле и честнее задать самим данным.
Что проверено
31 июля 2026 года. Мониторинг предшественника разобран по файлам в
configs/grafana/provisioning/ и configs/prometheus.yml репозитория
clickstream-ch-kafka-superset-demo: 28 панелей с запросами в дашбордах
ClickHouse, Kafka и Airflow, 17 — в дашборде генератора, 10 правил
оповещения.
Источник данных ClickHouse — плагин, в образе Grafana его нет. Проверено
запросом к живому стенду (/api/plugins?type=datasource): 19 встроенных
источников, ClickHouse среди них отсутствует. Плагин ставится сборкой своего
образа Grafana, как уже собираются свои образы Airflow и Superset. Установка
при старте контейнера отвергнута: она делает make up зависимым от сети и от
доступности каталога плагинов, то есть стенд перестаёт подниматься по причинам,
к нему не относящимся. Версия плагина закрепляется, как закреплены остальные.
Состав панелей выбран до этапа 9 намеренно: уроки пишутся отдельной работой (спека, раздел 10), но рассказать урок можно только про то, что дашборд показывает. Скопируй мы состав предшественника — урок неизбежно получился бы про пульс планировщика.
21 августа 2026 года дашборд «Данные» собран. Один пункт решения исполнен не буквально: у панели потока нет ряда «против вчерашнего». Сдвинуть ряд на модельные сутки значит записать ускорение мира в JSON дашборда — ровно ту пометку, от которой этот же ADR отговаривает выше, — а реальные сутки на стенде не с чем сравнивать. Довод целиком и остальное устройство дашборда — docs/architecture/monitoring/data.md.
Тогда же собраны «Кластер» и «Запросы». Довод про clusterAllReplicas
подтвердился с одной поправкой: очередь распределённых DDL лежит не у ноды, а в
keeper, и обе ноды читают её целиком — запрос вернул с каждой одни и те же 124
записи. Обёртка там не добавила бы правды, а удвоила бы каждую строку, поэтому
единственная панель «Кластера» без неё — эта. Keeper своих системных таблиц не
имеет вовсе, и панель по нему приходит из Prometheus.
«Запросы» получили на две панели больше, чем сказано выше. Разбор запросов по
посетителям продиктован ADR 0007: своя учётка
Grafana заведена там ровно затем, чтобы её запросы были отличимы от
человеческих.
Отдельная панель ошибок понадобилась потому, что отказ достаётся шарду: в
замере с принудительным пределом памяти каждая нода записала свой, и строка
шарда видна только без фильтра по инициатору. Здешний сюжет про тяжёлый
GROUP BY при этом кончается не отказом, а сбросом на диск
(ADR 0004) — отказ на стенде приходится вызывать
настройкой. Устройство обоих дашбордов —
cluster.md и
queries.md.