Files
clickstream-ch-kafka-supers…/docs/OPERATIONS.md
T
ddadminandDmitry Dementiev d97be5fa56 feat(monitoring): добавлен дашборд Grafana для мониторинга generator
- Зачем:
  - нужна визуализация метрик generator в реальном времени
  - Prometheus job уже настроен, не хватает Grafana dashboard
- Что:
  - добавлен provisioning-файл dashboards/generator-overview.json
  - 6 разделов: Overview, Events by Topic, Errors, Tick Statistics, Status, Info
  - Overview: Total Events/min (все 4 топика), Tick Duration (p50/p99)
  - Events by Topic: bar chart Events per Hour, Events Rate, Total Events
  - Errors: Total Errors, Error Rate, Errors by Topic (с 'or on() vector(0)')
  - Tick Statistics: Duration Distribution, Hour Factor (text), Tick Interval (text)
  - Status: Generator Status (threshold 120s), Generator Health (heartbeat), Time Since Last Tick
  - Info: команды и предупреждения о хардкоде GEN_TICK_SECONDS=5s
  - исправлены панели ошибок с 'or on() vector(0)' для корректного отображения 0
  - заменен heatmap на bar chart для стабильности
  - добавлены пояснения про Events/min = сумма 4 связанных топиков
  - Hour Factor синхронизирован с кодом генератора (00-05/09-18)
  - Generator Health: переименовано из State Management с value mappings
  - обновлены docs/OPERATIONS.md и generator/README.md
  - удален устаревший plans/generator-monitoring-plan.md
- Проверка:
  - дашборд открывается на http://localhost:3000/d/generator-overview
  - все панели отображают данные корректно (протестировано через Playwright)
  - ошибки показывают 0 вместо No data
  - Events/min корректно отображает сумму всех 4 топиков (~800-1000/min)
2026-06-09 17:27:17 +03:00

20 KiB
Raw Blame History

Operations Runbook

Операционный runbook для локального запуска и проверки пайплайна.

Локальный запуск

Базовые команды:

  • make up (или docker compose up -d)
  • make down (остановить и удалить контейнеры/сети проекта)
  • make clean (полная очистка: down -v --remove-orphans)
  • make ddl (применяет SQL из sql/ddl/00_databases.sql и sql/ddl/*/*.sql в ClickHouse)
  • make data (пересоздаёт топики и заливает данные в Kafka; по умолчанию полный объём, срез — LIMIT=50 make data)
  • make transform (запускает batch-процесс ODS -> DDS -> DM)
  • make superset-init (повторная инициализация Superset: подключение к ClickHouse, датасеты, дашборд)
  • docker compose ps
  • docker compose logs -f --tail=200 <service>
  • docker compose down (сохраняет named volumes, включая clickhouse-data)
  • docker compose down -v (удаляет named volumes, использовать осознанно)

Порты

Порты задаются в docker-compose.yml:

  • ClickHouse native: localhost:8002 (пользователь default, пароль 123456)
  • ClickHouse HTTP / play-консоль: http://localhost:9123/play (default / 123456)
  • Kafka: localhost:9092
  • Kafka UI: http://localhost:8082
  • Airflow: http://localhost:8080 (admin/admin)
  • Superset: http://localhost:8088 (admin/admin)
  • Prometheus: http://localhost:9090
  • Grafana: http://localhost:3000 (admin/admin)

Airflow DAGs

ddl_init

  • Запуск: ручной (Trigger DAG)
  • Параметр: verify_only (bool, default false)
  • Назначение: создаёт БД и таблицы в ClickHouse от 00_databases до 40_dm

kafka_load

  • Запуск: ручной (Trigger DAG with config)
  • Параметры:
    • limit (int, default 0) — количество строк (0 = все)
    • reset_topics (bool, default true) — пересоздать топики
  • Примеры:
{}
{"limit": 100}

etl_pipeline

  • Запуск: ручной (Trigger DAG with config)
  • Параметры:
    • full_refresh (bool, default true) — очистить DDS перед загрузкой
    • wait_stg_timeout_sec (int, default 600, minimum 30) — сколько секунд задача wait_for_stg_data ждёт появления данных в STG, прежде чем упасть по таймауту
  • Зависимость: требует наличия данных в STG (от kafka_load или make data)
  • Гейт целостности DDS: check_dds_integrity считает события без клика, а assert_dds_integrity роняет DAG при orphan_events > 0. Проверка идёт после load_dds и до load_dm_summary, чтобы DM не собирался поверх нарушенной связи dds.event -> dds.click. Для assert_dds_integrity задано retries=0: повтор не чинит уже собранную сироту и только задерживает явный failed-статус.

Генератор событий (автономный стриминг)

Автономный сервис для непрерывной генерации событий в Kafka. Работает независимо от Airflow DAGs.

Управление

# Запустить генератор
make generator-up

# Остановить генератор
make generator-down

# Перезапуск с пересборкой
make generator-restart

# Логи
make generator-logs

Конфигурация (env)

Переменная Описание По умолчанию
GEN_TICK_SECONDS Интервал между тиками 5
GEN_LAMBDA_BASE_PER_MIN Базовая интенсивность (событий/мин) 200
GEN_JITTER_PCT Процент вариативности 20
GEN_MIN_EVENTS_PER_TICK Минимум событий за тик 5
GEN_MAX_EVENTS_PER_TICK Максимум событий за тик 50

Топик истории

Генератор пишет историю батчей в топик generator_batch_history (JSON, ключ batch_id).

Важно: генератор требует работающей Kafka. Без Kafka генератор упадёт при старте или потеряет события.

# Чтение истории из Kafka
docker compose exec kafka /opt/kafka/bin/kafka-console-consumer.sh \
  --bootstrap-server kafka:29092 \
  --topic generator_batch_history \
  --from-beginning

Метрики

Prometheus метрики доступны на http://localhost:9109/metrics:

  • generator_events_total — счётчик отправленных событий
  • generator_publish_errors_total — ошибки публикации
  • generator_tick_duration_seconds — длительность тика

Мониторинг через Grafana

Dashboard URL: http://localhost:3000/d/generator-overview

Дашборд "Generator Overview" автоматически загружается при старте Grafana и содержит:

Раздел Панели Описание
Overview Events/min Скорость генерации событий в минуту
Tick Duration Медиана и p99 длительности тика
Last Successful Tick Время последнего успешного тика
Events by Topic Events per Hour (24h bar chart) Распределение событий по часам и топикам
Events Rate by Topic График по 4 топикам (browser, location, device, geo)
Total Events by Topic Суммарные счётчики по каждому топику
Errors Total Errors Общее число ошибок публикации
Error Rate Скорость ошибок (err/min)
Errors by Topic Ошибки разбиты по топикам
Tick Statistics Tick Duration Distribution p50, p95, p99 длительности тиков
Events per Tick Среднее число событий на тик
Hour Factor Текущий временной множитель (0.7/1.0/1.2)
Status Generator Status Статус работы (enabled/disabled)
Generator Health Статус активности (heartbeat last tick), не проверяет state save
Time Since Last Tick Время с последнего тика
Info Полезные команды и параметры конфигурации

Troubleshooting генератора

Нет данных на дашборде:

  1. Проверить, что генератор запущен: docker compose ps generator
  2. Проверить метрики напрямую: curl http://localhost:9109/metrics
  3. Проверить target в Prometheus: http://localhost:9090/targets (job: generator)

Высокий error rate:

  • Проверить доступность Kafka: docker compose ps kafka
  • Смотреть логи: make generator-logs
  • Проверить consumer lag: дашборд Kafka Overview

Длительные тики (p99 > 1s):

  • Проверить CPU/ресурсы контейнера
  • Возможно, высокая нагрузка на Kafka — проверить дашборд Kafka

Dashboard не загрузился:

# Перезагрузить provisioning Grafana
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/dashboards/reload

# Или пересоздать контейнер
docker compose restart grafana

Рекомендуемый сценарий (фаза 2)

# 1. Запуск инфраструктуры
make up

# 2. Инициализация схемы (один раз)
# Airflow UI -> DAGs -> ddl_init -> Trigger DAG

# 3. Загрузка данных через Airflow
# Airflow UI -> DAGs -> kafka_load -> Trigger DAG with config
# Параметры по умолчанию: limit=0, reset_topics=true

# 4. Запуск ETL
# Airflow UI -> DAGs -> etl_pipeline -> Trigger DAG with config
# {"full_refresh": true}

# 5. Проверка результатов
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 --query "SELECT count() FROM ods.browser_event"
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 --query "SELECT count() FROM dds.event"
docker compose exec -T clickhouse clickhouse-client --user=default --password=123456 --query "SELECT * FROM dm.dq_summary"

Быстрые проверки

  • Kafka ingest: наличие данных в stg.* и типизированных строк в ods.*.
  • Airflow UI: http://localhost:8080 показывает DAG ddl_init, kafka_load, etl_pipeline.
  • BI: витрина dm.v_events_enriched отвечает за разумное время при фильтре по дате.

Мониторинг

TL;DR после git pull

# Быстрый вариант (make)
make reload-monitoring
# Если мониторинг "залип" (No data/out of bounds) — жесткое восстановление:
make recover-monitoring

# Или вручную:
docker compose up -d prometheus grafana kafka-exporter statsd-exporter
docker compose restart prometheus statsd-exporter
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/datasources/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/dashboards/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/alerting/reload

Если менялся configs/prometheus_ch.xml: docker compose restart clickhouse.

Prometheus + Grafana для ClickHouse, Kafka и Airflow

Стек мониторинга поднимается вместе с остальной инфраструктурой:

# Проверить статус сервисов мониторинга
docker compose ps prometheus grafana

# Проверить скрейп ClickHouse в Prometheus
curl -s http://localhost:9090/api/v1/targets | grep -o '"health":"[^"]*"'

Конфигурация

  • ClickHouse: встроенный Prometheus endpoint (/metrics на порту 9126)
  • Kafka: через kafka-exporter (порт 9308)
  • Airflow: через statsd-exporter (StatsD → Prometheus, порт 9102)
    • Airflow отправляет метрики в StatsD-формате на statsd-exporter:8125
    • Mapping конфигурация: configs/statsd_mapping.yml
  • Grafana provisioning (configs/grafana/provisioning/):
    • Дашборды: ClickHouse Overview, Kafka Overview, Airflow Overview, Generator Overview
    • Алерты: ClickHouse, Kafka, Airflow

После git pull: быстрый апдейт мониторинга

Если прилетели изменения в configs/grafana/provisioning/* или configs/prometheus.yml, примените их так:

# Рекомендуемый способ (через make)
make reload-monitoring
# Если метрики пропали/залипли:
make recover-monitoring

# Или вручную:
docker compose rm -sf prometheus statsd-exporter
docker compose up -d prometheus grafana kafka-exporter statsd-exporter
docker compose restart airflow-scheduler airflow-webserver
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/datasources/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/dashboards/reload
curl -s -u admin:admin -X POST http://localhost:3000/api/admin/provisioning/alerting/reload

Проверка результата:

# Дашборды и алерты
curl -s -u admin:admin http://localhost:3000/api/v1/provisioning/alert-rules | grep -o '"title":"[^"]*"'

# Kafka метрики
curl -s http://localhost:9090/api/v1/targets | grep kafka
curl -s http://localhost:9308/metrics | grep "^kafka_brokers"

Если в пулле изменился configs/prometheus_ch.xml, дополнительно перезапустите ClickHouse:

docker compose restart clickhouse

Если дашборд Kafka не загрузился (ошибка "Dashboard title cannot be empty" в логах), пересоздайте контейнер Grafana:

docker compose stop grafana && docker compose rm -f grafana && docker compose up -d grafana

Дашборд ClickHouse Overview

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

Раздел Метрики
System Health CPU Usage, Memory Resident, Memory Code
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

Принятое решение по метрикам: сверили naming через Context7 (/clickhouse/clickhouse-docs, раздел Prometheus interface) и заменили недоступные в 25.1 серии на фактически экспортируемые (ClickHouseProfileEvents_InsertedRows, ClickHouseAsyncMetrics_TotalPartsOfMergeTreeTables, ClickHouseMetrics_Parts*).

Дашборд Kafka Overview

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

Раздел Метрики
Cluster Health Brokers Up, Topics, Total Partitions, Consumer Groups
Throughput Messages In / sec by Topic
Consumers Consumer Lag by Group
Partitions Partition Offsets (Current)

Источник метрик: kafka-exporter (danielqsj/kafka-exporter), формат конфигурации подтверждён через Context7 (/danielqsj/kafka_exporter, /prometheus/docs).

Проверка метрик

# Prometheus собирает метрики ClickHouse
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseAsyncMetrics_MemoryResident"
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseProfileEvents_Query"

# Prometheus собирает метрики Kafka
curl -s "http://localhost:9090/api/v1/query?query=kafka_brokers"
curl -s "http://localhost:9090/api/v1/query?query=kafka_consumergroup_lag"

# Прямая проверка kafka-exporter
curl -s http://localhost:9308/metrics | grep "^kafka_"
# Проверить, что Prometheus собирает метрики
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseAsyncMetrics_MemoryResident"

# Проверить счётчик запросов
curl -s "http://localhost:9090/api/v1/query?query=ClickHouseProfileEvents_Query"

Алерты Grafana

ClickHouse Alerts — provisioning-файл: configs/grafana/provisioning/alerting/clickhouse-alert-rules.yml

Настроены правила:

  • ClickHouse Failed Queries Raterate(ClickHouseProfileEvents_FailedQuery[5m]) > 0 в течение 2m
  • ClickHouse Memory Resident HighMemoryResident / OSMemoryTotal * 100 > 85 в течение 5m
  • ClickHouse Parts Active HighClickHouseMetrics_PartsActive > 500 в течение 10m

Kafka Alerts — provisioning-файл: configs/grafana/provisioning/alerting/kafka-alert-rules.yml

Настроены правила:

  • Kafka Broker Downkafka_brokers < 1 в течение 1m
  • Kafka Consumer Lag Highkafka_consumergroup_lag > 10000 в течение 5m
  • Kafka No Messages Producedrate(kafka_topic_partition_current_offset[5m]) < 0.1 в течение 10m
  • Kafka Consumer Group Missing не включён: для демо-стенда даёт шум на стартовых прогонах и не повышает диагностику по сравнению с lag/throughput.

Проверка и reload без рестарта контейнера:

# Список правил unified alerting
curl -s -u admin:admin http://localhost:3000/api/v1/provisioning/alert-rules

# Принудительно перечитать provisioning alerting
curl -s -X POST -u admin:admin http://localhost:3000/api/admin/provisioning/alerting/reload

Troubleshooting мониторинга

Общие проблемы:

  • "No data" в Grafana: проверить, что Prometheus видит target (Status -> Targets в UI)
  • Dashboard не загрузился: проверить логи Grafana — provisioning работает при первом старте контейнера
  • Prometheus spam out of bounds и дашборды пустые: выполнить make recover-monitoring

ClickHouse:

  • Метрики не обновляются: ClickHouse экспортирует метрики на 0.0.0.0:9126 внутри сети Docker

Kafka:

  • connection refused к Kafka: проверить, что kafka-exporter использует kafka:29092 (внутренняя сеть), не localhost:9092
  • Метрики Kafka не появляются: проверить, что kafka-exporter подключился к Kafka — docker compose logs kafka-exporter
  • Нет консьюмер-групп: kafka-exporter показывает lag только при наличии активных консьюмеров с закоммиченными offset

Troubleshooting

  • etl_pipeline падает с ошибкой схемы: сначала запустить ddl_init.
  • git pull падает с Permission denied на data/* или configs/grafana/provisioning/*:
    • Причина: локально есть файлы/каталоги не вашего пользователя (часто после запуска контейнеров с root-пользователем).
    • Диагностика:
      ls -ld data configs/grafana/provisioning
      ls -l data | head -n 20
      
    • Быстрое восстановление:
      # Владелец и права для рабочей копии репозитория
      sudo chown -R "$USER:$USER" .
      find . -type d -exec chmod u+rwx {} \;
      find . -type f -exec chmod u+rw {} \;
      
    • После восстановления повторить git pull --ff-only.
    • Не запускать git через sudo.
  • grafana перезапускается с ошибкой attempt to write a readonly database:
    • Причина: старый grafana_lib содержит grafana.db, созданный root-пользователем.
    • Простой recovery (сбросить только volume Grafana):
      docker compose stop grafana
      docker volume ls | grep grafana_lib
      docker volume rm <project>_grafana_lib
      docker compose up -d grafana
      
  • В Superset ошибки DB engine Error и Cannot load filter, а в логах есть Can't load plugin: sqlalchemy.dialects:clickhouse.connect:
    • Причина: некорректный URI диалекта ClickHouse (clickhouse+connect://...).
    • Используйте URI clickhousedb://... и пересоберите сервисы Superset:
      docker compose build superset superset-init
      docker compose up -d clickhouse
      docker compose up -d --force-recreate superset-init superset
      
  • После docker compose down -v нужно повторно прогнать: ddl_init -> kafka_load -> etl_pipeline.
  • После make clean/down -v Superset стартует, но витрины dm.* ещё пустые или отсутствуют до прогона ETL; после ddl_init -> kafka_load -> etl_pipeline выполнить make superset-init.
  • Для демо по умолчанию использовать малый срез данных; полный прогон делать осознанно.