Files
ddadminandClaude Opus 4.8 cbf8b2d770 fix(course): правки по итогам слепого ревью лаб 07/08 (#22)
Зачем: два слепых ревью (Codex CODE-1..9, Claude TASK-1..2) и
перепроверки нашли дефекты в лабах и метадоках; финал лабы 08
переделан по решению пользователя.

Что:
- канонический сброс в README курса теперь снимает DAG'и с паузы
  (все создаются на паузе);
- имя дашборда исправлено на «E-commerce Analytics Dashboard»;
- финал лабы 08: вместо мифа «users == sessions на статике» —
  вернувшийся пользователь через границу заморозки и измеренное
  обещание свежести; §2 велит записать границы и время (§6 их требует);
- CONTEXT.md: эталонный мир — замороженный живой,
  4 056 пользователей / 26 083 визита, возвраты уже есть;
- уроки 5–6 ведут в обязательный маршрут, живое упражнение
  урока 5 требует канонический сброс;
- контрактные тесты: убран якорь на удалённую команду; добавленные
  на триаже тесты-цитаты срезаны до устойчивых инвариантов
  (прозаический легаси-жанр — issue #24);
- handoff обновлён до текущего состояния.

Проверка: make test (219 generator + 31 contract) и make lint зелёные;
SQL вернувшегося пользователя проверен на эфемерном ClickHouse 25.1
(на полном наборе — в #23).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:48:02 +03:00

23 KiB
Raw Permalink Blame History

Урок 5. Мониторинг в Prometheus и Grafana

Формат: наблюдение с управляемым сбоем — будешь смотреть метрики и алерты, а в конце ненадолго остановишь один сервис и вернёшь его обратно. Пререквизит: пройден урок 4 (ты запускал etl_pipeline, видел зелёный и красный DAG-run и понимаешь, где Airflow показывает судьбу одного прогона). Эталонные пути: configs/prometheus.yml, configs/statsd_mapping.yml, configs/grafana/provisioning/.

Поток метрик одной строкой: ClickHouse / Kafka / Airflow → exporters → Prometheus → Grafana dashboards → Grafana alerts

О чём урок простыми словами: Airflow показывает конкретный запуск пайплайна, а мониторинг показывает состояние всего стенда. Мы посмотрим, живы ли сервисы, есть ли лаг в Kafka, не застрял ли Airflow, и как Grafana подсвечивает поломку.


1. Зачем и где в проде

После урока 4 у нас есть управляемый DAG: если в DDS появляются сироты, Airflow красит задачу и не выпускает DM дальше. Это важно, но это взгляд изнутри одного запуска.

В проде нужен ещё один слой: мониторинг. Он отвечает на другие вопросы:

  • жив ли ClickHouse и отдаёт ли метрики;
  • видит ли Kafka брокер, топики и consumer lag;
  • работает ли scheduler Airflow;
  • есть ли очередь задач;
  • появились ли failed queries или failed tasks;
  • что изменилось не в одном DAG-run, а во времени.

Prometheus — база временных рядов для метрик. Он регулярно ходит в endpoints сервисов и забирает числа: память, счётчики запросов, lag, heartbeat scheduler-а. Такой регулярный опрос называется scrape («сбор метрик»).

Exporter — маленький мост между сервисом и Prometheus. Если сервис не отдаёт метрики в удобном для Prometheus виде, exporter переводит их. В нашем стенде:

  • ClickHouse сам отдаёт /metrics на порту 9126;
  • Kafka читается через kafka-exporter на порту 9308;
  • Airflow отправляет StatsD-метрики в statsd-exporter, а тот отдаёт Prometheus endpoint на порту 9102.

Grafana — витрина поверх метрик. В ней мы смотрим дашборды и алерты. Дашборд отвечает «что сейчас происходит?», а алерт отвечает «какое условие уже достаточно плохое, чтобы привлечь внимание?».

В проде иначе. Метрики отправляют в общий мониторинг компании, алерты уходят в Slack, PagerDuty или другой on-call канал, а пороги подбирают по SLO и истории нагрузки. Но учебный паттерн тот же: сервис отдаёт метрики, Prometheus их собирает, Grafana помогает увидеть состояние и поломку.


2. Руки: открываем дашборды и targets

Подготовь стенд по канонической инструкции курса. После успешного world_init эталонный мир уже прошёл путь Kafka → STG → ODS → DDS → DM, а в Airflow есть завершённый прогон etl_pipeline.

Нам нужны не идеальные объёмы, а живой стенд, в котором есть Kafka-топики, строки в ClickHouse и хотя бы один прогон Airflow.

Проверяем Prometheus targets

Открой Prometheus: http://localhost:9090. В меню зайди в Status → Targets.

Ожидаем основные job:

Job Target внутри Docker Что это значит
clickhouse clickhouse:9126 ClickHouse отдаёт встроенный Prometheus endpoint
kafka kafka-exporter:9308 kafka-exporter подключился к Kafka и отдаёт метрики
airflow statsd-exporter:9102 statsd-exporter отдаёт метрики Airflow в формате Prometheus
generator generator:9109 live-генератор отдаёт свои метрики, только когда явно запущен

У clickhouse, kafka и airflow состояние должно быть UP. generator на базе импортированного мира может быть DOWN: живой поток включается отдельно через make generator-continue. Если один из трёх основных target DOWN, Grafana дальше будет показывать No data или старые значения.

То же можно проверить из терминала:

curl -s http://localhost:9090/api/v1/targets | grep -o '"job":"[^"]*"'
curl -s http://localhost:9090/api/v1/targets | grep -o '"health":"[^"]*"'

Открываем Grafana

Открой Grafana: http://localhost:3000 (логин admin, пароль admin).

Если Grafana просит сменить пароль после первого входа, для учебного стенда нажми Skip. Так все инструкции в курсе останутся одинаковыми: локальный пользователь admin, пароль admin. Если ты уже сменил пароль раньше, используй свой новый пароль.

После входа ты попадаешь на домашний экран Grafana. Минимальная навигация на этот урок:

  • Dashboards — раздел с готовыми дашбордами. Обычно он доступен из левого меню или через поиск по слову Dashboards;
  • Alerting → Alert rules — список правил алертов. Он понадобится в управляемой правке;
  • строка поиска сверху помогает быстро найти ClickHouse Overview, Kafka Overview или Airflow Overview, если меню выглядит иначе.

В Dashboards должны быть четыре дашборда:

  • ClickHouse Overview;
  • Kafka Overview;
  • Airflow Overview;
  • Generator Overview — про живой поток; на базе импортированного мира он пуст, как и target generator выше, и в этом уроке не понадобится.

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

ClickHouse Overview

URL: http://localhost:3000/d/clickhouse-overview/clickhouse-overview

Главные панели:

  • System Health — общий блок про ресурсное состояние;
  • CPU Usage, Memory Resident, Memory Code — насколько ClickHouse нагружен и сколько памяти держит;
  • Query Performance — блок про запросы;
  • Queries per Second, Active Queries, Failed Queries (total), Total Queries — есть ли запросная активность и ошибки;
  • Inserted Rows/sec — идут ли вставки;
  • MergeTree Storage, Total Parts, Parts by State, Total Merges, Merges per Second — что происходит с MergeTree-частями.

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

Kafka Overview

URL: http://localhost:3000/d/kafka-overview/kafka-overview

Главные панели:

  • Cluster Health — жив ли Kafka-брокер и видны ли топики;
  • Brokers Up, Topics, Total Partitions, Consumer Groups — базовый снимок кластера;
  • Throughput и Messages In / sec by Topic — идут ли новые сообщения в топики;
  • Consumer Lag by Group — насколько consumer group отстаёт от конца топика;
  • Partitions и Partition Offsets (Current) — текущие offset-ы по партициям.

Consumer lag — это разница между тем, что уже лежит в топике, и тем, что consumer group успела прочитать. В нашем стенде ClickHouse обычно читает быстро, поэтому большой устойчивый lag не ожидается.

Есть важная оговорка из урока 0: ClickHouse-движок не всегда показывает свой прогресс как обычная Kafka-группа. Поэтому в Kafka UI колонки offset/lag у ch_stg_* могут быть пустыми, а в Grafana панель lag может быть пустой или нулевой. Это не конфликт между уроками. Для точной проверки чтения со стороны ClickHouse смотри system.kafka_consumers, а Grafana здесь используй как общий сигнал: появился ли большой lag, который не уходит.

Airflow Overview

URL: http://localhost:3000/d/airflow-overview/airflow-overview

Главные панели:

  • Scheduler Health — жив ли scheduler;
  • DAG Bag Size — сколько DAG-ов Airflow видит;
  • Parse Time — сколько времени занимает разбор DAG-файлов;
  • Scheduler Heartbeat Rate — продолжает ли scheduler отправлять heartbeat;
  • Executor Status, Open Slots, Queued Tasks, Running Tasks, Executor Tasks Over Time — хватает ли executor-у места для задач;
  • Task Performance, Task Duration (avg), Task Failures vs Success Rate — как ведут себя задачи во времени.

После урока 4 тебе знаком красный etl_pipeline в UI Airflow. На этом дашборде та же проблема видна шире: не «какая task упала в одном run», а «есть ли failed tasks как метрика во времени».


3. Загляни внутрь

Открой configs/prometheus.yml. Это короткая карта того, откуда Prometheus забирает метрики.

scrape_configs: кого опрашивает Prometheus

В файле четыре блока:

scrape_configs:
  - job_name: "clickhouse"
    metrics_path: "/metrics"
    static_configs:
      - targets: ["clickhouse:9126"]

job_name — имя источника метрик. Его ты видел в Prometheus Targets. metrics_path говорит, куда ходить за метриками. targets использует внутренние имена Docker Compose, а не localhost: Prometheus живёт внутри compose-сети и ходит к соседним контейнерам по их service name.

Kafka, Airflow и generator устроены так же, но источники разные:

  • kafkakafka-exporter:9308;
  • airflowstatsd-exporter:9102;
  • generatorgenerator:9109, только когда live-генератор явно запущен. Без live этот target может быть DOWN, как в проверке Prometheus выше.

Почему Airflow идёт через StatsD

Открой configs/statsd_mapping.yml. Airflow отправляет метрики в StatsD-формате, например airflow.scheduler_heartbeat. Prometheus так напрямую не читает, поэтому между ними стоит statsd-exporter.

Mapping переводит имена в Prometheus-стиль:

StatsD-метрика Airflow Prometheus-метрика Где видна
airflow.scheduler_heartbeat airflow_scheduler_heartbeat_total Scheduler Heartbeat Rate
airflow.executor.queued_tasks airflow_executor_queued_tasks Queued Tasks
airflow.ti.finish.*.*.failed airflow_task_failures_total Task Failures vs Success Rate
airflow.dag.*.*.duration airflow_task_duration_seconds Task Duration (avg)

Звёздочки в mapping — это части имени, которые становятся label-ами. Например, у task duration появляются dag_id и task_id, чтобы в Grafana можно было отличить один DAG и одну task от других.

Grafana provisioning: дашборды и алерты как файлы

Открой папку configs/grafana/provisioning/.

В ней три вида настройки:

  • datasources/prometheus.yml — говорит Grafana, где находится Prometheus;
  • dashboards/*.json — описывает панели дашбордов;
  • alerting/*-alert-rules.yml — описывает правила алертов.

Это называется provisioning: Grafana получает дашборды и алерты из файлов при старте, а не только через ручные клики в UI. Для стенда это удобно: поднял compose — получил одинаковую Grafana.

Какие алерты уже есть

Открой Alerting → Alert rules в Grafana. Там должны быть правила:

Группа Правило Условие простыми словами
ClickHouse Alerts ClickHouse Failed Queries Rate появились failed queries
ClickHouse Alerts ClickHouse Memory Resident High ClickHouse занял больше 85% памяти
ClickHouse Alerts ClickHouse Parts Active High активных MergeTree-частей больше 500
Kafka Alerts Kafka Broker Down Prometheus видит меньше одного Kafka-брокера
Kafka Alerts Kafka Consumer Lag High lag больше 10000
Kafka Alerts Kafka No Messages Produced в топики долго почти не идут новые сообщения
Airflow Alerts Airflow Scheduler Down heartbeat scheduler-а почти исчез
Airflow Alerts Airflow Queue Backlog в очереди больше 50 задач
Airflow Alerts High Task Failure Rate растёт rate failed tasks
Airflow Alerts High DAG Parse Time DAG-файлы долго парсятся

Не все эти правила обязаны быть тихими в учебном стенде. После импорта эталонной базы живой поток не запущен, поэтому новые сообщения не приходят. Из-за этого Kafka No Messages Produced может перейти в Alerting на полностью здоровом стенде: алерт честно говорит, что потока сейчас нет, а не что импорт сломан. Если хочешь проверить правило в спокойном состоянии, явно включи живой поток:

make generator-continue

После наблюдения останови live-генератор, чтобы он не менял стенд дальше:

make generator-down

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


4. Управляемая правка: остановим scheduler и увидим алерт

Теперь сделаем маленькую поломку, которую легко вернуть назад: остановим только airflow-scheduler. Web UI Airflow останется доступен, ClickHouse и Kafka не трогаем.

Шаг 1. Убедись, что сейчас всё живо

Открой Grafana → Airflow Overview и найди панель Scheduler Heartbeat Rate.

Потом открой Alerting → Alert rules и найди правило Airflow Scheduler Down. Перед экспериментом оно должно быть в состоянии Normal (не Alerting).

Можно проверить и командой:

docker compose ps airflow-scheduler

Шаг 2. Останови scheduler

docker compose stop airflow-scheduler

Подожди 2-3 минуты. У правила Airflow Scheduler Down стоит окно for: 2m, поэтому алерт не обязан покраснеть мгновенно. Это нормальное поведение: мониторинг защищается от коротких миганий.

Что ожидаем:

  • в Airflow Overview панель Scheduler Heartbeat Rate падает к нулю или перестаёт обновляться;
  • в Alerting → Alert rules правило Airflow Scheduler Down переходит в Alerting;
  • новые DAG-runs не должны нормально планироваться, потому что scheduler остановлен.

Это и есть отличие мониторинга от ручной проверки: тебе не нужно помнить команду для heartbeat. Условие уже записано в alert rule.

Верни как было

Сразу верни scheduler:

docker compose up -d airflow-scheduler

Подожди ещё 2-3 минуты и проверь:

  • docker compose ps airflow-scheduler показывает running/up;
  • Scheduler Heartbeat Rate снова растёт;
  • Airflow Scheduler Down выходит из Alerting.

Если Grafana или Prometheus после экспериментов показывают No data, восстанови мониторинг штатной командой:

make reload-monitoring

Если это не помогло и видишь out of bounds или залипшие старые значения:

make recover-monitoring

5. Проверь себя

Действие Где смотреть Что ожидать
открыть Prometheus targets http://localhost:9090 → Status → Targets clickhouse, kafka, airflow в состоянии UP; generator может быть DOWN без live
открыть ClickHouse Overview Grafana dashboards панели Queries per Second, Failed Queries (total), Inserted Rows/sec не пустые
открыть Kafka Overview Grafana dashboards видны Brokers Up, Topics, Consumer Lag by Group
открыть Airflow Overview Grafana dashboards видны Scheduler Heartbeat Rate, Queued Tasks, Task Failures vs Success Rate
остановить airflow-scheduler Grafana alert rules Airflow Scheduler Down переходит в Alerting после окна ожидания
вернуть airflow-scheduler Grafana alert rules и docker compose ps сервис снова running/up, алерт возвращается в норму

6. Что должно получиться

После урока у тебя на руках — видимый результат:

  • скрин Prometheus Targets, где clickhouse, kafka и airflow находятся в UP;
  • скрин Grafana с правилом Airflow Scheduler Down в Alerting после остановки scheduler-а;
  • короткое объяснение своими словами: почему Airflow UI и Grafana отвечают на разные вопросы.

Проверь себя на словах — примерно эти вопросы всплывут на еженедельном созвоне:

  • зачем Prometheus нужен отдельно от Grafana;
  • чем exporter отличается от самого сервиса;
  • почему Airflow-метрики проходят через statsd-exporter;
  • что такое scrape target;
  • что показывает consumer lag;
  • почему алерт Airflow Scheduler Down не краснеет в ту же секунду, когда ты остановил сервис;
  • почему после эксперимента нужно явно вернуть airflow-scheduler.

Если ответ про Airflow UI и Grafana получается одним и тем же, вернись к началу урока. Airflow UI удобен для разбора конкретного DAG-run. Grafana удобна для состояния системы во времени.


Мост к следующему шагу

Теперь ты видишь состояние пайплайна со стороны: где идут данные, где растёт отставание и где сработал алерт. В уроке 6 у готовых витрин появится потребитель — дашборд в Superset.