docs(generator): закрыты находки финального ревью цепочки
- Зачем: - финальный review должен видеть согласованные PRD, issue, курс, Superset и архитектурные документы. - Что: - обновлены PRD, чекбоксы закрытых issue и журнал coordinator-loop. - синхронизированы архитектура, карта репозитория, CONTEXT и курс со startup-history-путём. - убраны старые маркеры Superset-геокарты после перехода на Top Countries. - Проверка: - rg-проверки финального review по PRD, issue и Superset-маркерам. - git diff --cached --check.
This commit is contained in:
1 parent
3d4e13c541
commit
f8b419d84d
18 files changed
+181
-119
No files matched your search
+32
-33
@@ -27,12 +27,12 @@
|
||||
flowchart LR
|
||||
subgraph AF["Airflow"]
|
||||
DAG1["ddl_init"]
|
||||
DAG2["kafka_load (bootstrap)"]
|
||||
DAG2["generator_control"]
|
||||
DAG3["etl_pipeline"]
|
||||
end
|
||||
|
||||
subgraph GEN["Generator"]
|
||||
G["generator-service (steady-stream)"]
|
||||
G["generator-service"]
|
||||
end
|
||||
|
||||
subgraph Kafka["Kafka"]
|
||||
@@ -57,8 +57,8 @@ flowchart LR
|
||||
V[витрины VIEW]
|
||||
end
|
||||
|
||||
DAG2 -->|bootstrap JSONL| K
|
||||
G -->|stream events| K
|
||||
DAG2 -->|startup-history backfill/import| K
|
||||
G -->|live после make generator-continue| K
|
||||
K -->|MV| S
|
||||
S -->|batch| O
|
||||
O -->|argMax + JOIN| D1 & D2
|
||||
@@ -69,10 +69,10 @@ flowchart LR
|
||||
DAG3 -.->|batch| ODS & DDS
|
||||
```
|
||||
|
||||
В учебном стенде предусмотрены два пути ingest:
|
||||
В учебном стенде предусмотрены два пути загрузки:
|
||||
|
||||
- `bootstrap`: DAG `kafka_load` для разового/контрольного прогона из `data/*.jsonl`;
|
||||
- `steady-stream`: автономный генератор, публикующий события в Kafka непрерывно.
|
||||
- `startup-history`: DAG `generator_control` создаёт или импортирует историю, запускает ETL и проверяет витрины;
|
||||
- `live`: генератор запускается явно через `make generator-continue`, когда нужна непрерывная подача новых событий.
|
||||
|
||||
### Слои и их назначение
|
||||
|
||||
@@ -80,7 +80,7 @@ flowchart LR
|
||||
flowchart LR
|
||||
subgraph AF["Airflow"]
|
||||
DAG1["ddl_init"]
|
||||
DAG2["kafka_load (bootstrap)"]
|
||||
DAG2["generator_control"]
|
||||
DAG3["etl_pipeline"]
|
||||
end
|
||||
|
||||
@@ -106,8 +106,8 @@ flowchart LR
|
||||
DM_T["VIEW"]
|
||||
end
|
||||
|
||||
DAG2 -->|bootstrap JSONL| KAFKA
|
||||
G -->|steady-stream| KAFKA
|
||||
DAG2 -->|startup-history| KAFKA
|
||||
G -->|live| KAFKA
|
||||
KAFKA -->|MV| STG_T
|
||||
STG_T -->|batch| ODS_T
|
||||
ODS_T -->|argMax + JOIN| DDS_T -->|VIEW| DM_T
|
||||
@@ -376,7 +376,6 @@ sequenceDiagram
|
||||
Compose->>K: docker compose up -d kafka
|
||||
Compose->>CH: docker compose up -d clickhouse
|
||||
Compose->>Airflow: docker compose up -d airflow-*
|
||||
Compose->>Gen: docker compose up -d generator
|
||||
Compose-->>User: ✅ Инфраструктура готова
|
||||
|
||||
User->>Airflow: Trigger ddl_init
|
||||
@@ -387,14 +386,13 @@ sequenceDiagram
|
||||
Airflow->>CH: sql/ddl/dm/40_dm.sql
|
||||
CH-->>User: ✅ Структура БД создана
|
||||
|
||||
alt Bootstrap режим
|
||||
User->>Airflow: Trigger kafka_load
|
||||
Airflow->>K: precheck + prepare_topics
|
||||
loop 4 файла
|
||||
Airflow->>K: KafkaProducer.send(topic, json_line)
|
||||
end
|
||||
K-->>User: ✅ Данные в Kafka
|
||||
else Streaming режим
|
||||
alt Startup-history режим
|
||||
User->>Airflow: Trigger generator_control (backfill/import)
|
||||
Airflow->>K: события стартовой истории
|
||||
Airflow->>Airflow: trigger etl_pipeline + check
|
||||
K-->>User: ✅ История в Kafka и витринах
|
||||
else Live режим
|
||||
User->>Compose: make generator-continue
|
||||
loop каждые 1-10 секунд
|
||||
Gen->>K: send N_t (Poisson) в 4 топика
|
||||
end
|
||||
@@ -634,32 +632,33 @@ INSERT INTO dm.daily_traffic SELECT * FROM dm.v_daily_traffic;
|
||||
|
||||
### Airflow-оркестрация
|
||||
|
||||
Инфраструктура Airflow развёрнута и отвечает за DDL/ETL.
|
||||
Генератор работает отдельно и не управляется через Airflow DAG-и.
|
||||
Инфраструктура Airflow развёрнута и отвечает за DDL/ETL и стартовую историю.
|
||||
Живой генератор контейнеров запускается отдельно через Makefile.
|
||||
|
||||
```python
|
||||
# airflow/dags/ddl_init_dag.py — создание баз/таблиц (ручной запуск при bootstrap)
|
||||
# airflow/dags/kafka_load_dag.py — bootstrap-загрузка JSONL в Kafka (через kafka-python)
|
||||
# airflow/dags/ddl_init_dag.py — создание баз/таблиц
|
||||
# airflow/dags/generator_control_dag.py — backfill/import/check стартовой истории
|
||||
# airflow/dags/etl_pipeline_dag.py — основной ETL (STG→ODS→DDS→DM)
|
||||
# airflow/dags/kafka_load_dag.py — архивный ручной путь из JSONL, не основной контур
|
||||
|
||||
# Учебный формат:
|
||||
# - DDL и трансформации выполняются явными SQL-task через ClickHouseOperator;
|
||||
# - SQL-файлы вызываются по фиксированным путям;
|
||||
# - ingest может идти двумя путями:
|
||||
# 1) bootstrap через DAG `kafka_load`;
|
||||
# 2) непрерывный поток через автономный `generator-service`.
|
||||
# - загрузка может идти двумя путями:
|
||||
# 1) startup-history через DAG `generator_control`;
|
||||
# 2) live-поток через явный `make generator-continue`.
|
||||
#
|
||||
# Базовый demo-сценарий:
|
||||
# ddl_init -> kafka_load -> etl_pipeline
|
||||
# ddl_init -> generator_control(backfill/import) -> etl_pipeline -> check
|
||||
# Расширенный учебный сценарий:
|
||||
# generator-service (continuous) + периодический etl_pipeline
|
||||
# make generator-continue + периодический etl_pipeline
|
||||
```
|
||||
|
||||
**DAG `kafka_load`**:
|
||||
- Загрузка данных из `data/*.jsonl` в Kafka через `kafka-python`
|
||||
- TaskGroup `precheck`: проверка Kafka, файлов, параметров
|
||||
- TaskGroup `ingest`: создание топиков → параллельная загрузка 4 потоков → проверка
|
||||
- Параметры: `limit` (0 = все), `reset_topics`
|
||||
**DAG `generator_control`**:
|
||||
- `backfill`: создаёт стартовую историю через генератор
|
||||
- `import`: импортирует портативный артефакт стартовой истории
|
||||
- `check`: сверяет ClickHouse с manifest стартовой истории
|
||||
- После `backfill` и `import` запускает `etl_pipeline` с `full_refresh`
|
||||
|
||||
**Подключение к ClickHouse:**
|
||||
- Connection: `clickhouse_default`
|
||||
|
||||
+2
-1
@@ -588,7 +588,8 @@ make generated-history-check
|
||||
## Быстрые проверки
|
||||
|
||||
- Kafka ingest: наличие данных генератора в `stg.*` и типизированных строк в `ods.*`.
|
||||
- Airflow UI: `http://localhost:8080` показывает DAG `ddl_init`, `kafka_load`, `etl_pipeline`.
|
||||
- Airflow UI: `http://localhost:8080` показывает DAG `ddl_init`, `generator_control`,
|
||||
`kafka_load`, `etl_pipeline`; основной ручной пульт генератора — `generator_control`.
|
||||
- BI: витрина `dm.v_events_enriched` отвечает за разумное время при фильтре по дате.
|
||||
|
||||
---
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
### Airflow (ручной и учебный путь запуска)
|
||||
|
||||
- `airflow/dags/ddl_init_dag.py` — инициализация схемы ClickHouse
|
||||
- `airflow/dags/generator_control_dag.py` — Airflow-пульт стартовой истории: backfill/import/check
|
||||
- `airflow/dags/kafka_load_dag.py` — архивная загрузка в Kafka из JSONL; не основной источник аналитики
|
||||
- `airflow/dags/etl_pipeline_dag.py` — ETL процесс STG -> ODS -> DDS -> DM
|
||||
- `airflow/dags/utils/kafka_helpers.py` — helper-функции для Kafka
|
||||
|
||||
@@ -68,17 +68,17 @@ KPI разложены в одну строку по 12-колоночной с
|
||||
|
||||
#### География
|
||||
- **🌍 Top Countries by Events** — top-15 стран по количеству событий
|
||||
(`COUNT(*)`, единицы — события, штуки). Столбцы заменили legacy world map:
|
||||
(`COUNT(*)`, единицы — события, штуки). Столбцы заменили прежнюю геовизуализацию:
|
||||
на текущем разреженном распределении так видны страна, значение, порядок и
|
||||
tooltip. Перекос стран приходит из гео-фактуры статического сида
|
||||
`geo_by_click_id`; своя генерация гео описана как отдельный будущий шаг в
|
||||
ADR-0006 и не лечится настройкой чарта.
|
||||
|
||||
> **Что проверили по Superset.** Через MCP Context7 проверили `/apache/superset`:
|
||||
> legacy world map описан как отдельный legacy-плагин, а ECharts bar chart имеет
|
||||
> прежний геоплагин описан как legacy-плагин, а ECharts bar chart имеет
|
||||
> штатные параметры `show_legend`, `rich_tooltip`, подписи осей и формат чисел.
|
||||
> Поэтому для разреженной географии выбран top-N bar chart
|
||||
> (`viz_type: echarts_timeseries_bar`), а не донастройка `world_map`.
|
||||
> (`viz_type: echarts_timeseries_bar`), а не донастройка прежней геовизуализации.
|
||||
|
||||
#### Маркетинг
|
||||
- **🔗 UTM Effectiveness Table** — таблица эффективности UTM-меток
|
||||
@@ -119,7 +119,7 @@ KPI разложены в одну строку по 12-колоночной с
|
||||
| 🌐 Browser | `browser_name` | Multi-select | Charts на `dm.v_events_enriched` |
|
||||
|
||||
Фильтры работают через левую панель Superset. Click-to-filter между виджетами не включен:
|
||||
клик по сектору pie chart, карте, строке таблицы или funnel не меняет остальные charts.
|
||||
клик по сектору pie chart, столбцу Top Countries, строке таблицы или funnel не меняет остальные charts.
|
||||
|
||||
Фильтр применяется только к charts, где есть нужное поле. Агрегированные витрины
|
||||
`dm.v_utm_effectiveness` и `dm.v_top_pages_daily` содержат `event_date`, но не содержат
|
||||
@@ -182,7 +182,7 @@ python /app/superset_init/init_superset.py
|
||||
1. Перейдите в **Charts → + Chart**
|
||||
2. Выберите датасет (например, `dm.v_events_enriched`)
|
||||
3. Настройте визуализацию:
|
||||
- **Viz Type:** Big Number / Line Chart / Pie Chart / World Map / Table
|
||||
- **Viz Type:** Big Number / Line Chart / Pie Chart / ECharts Bar / Table
|
||||
- **Metrics:** COUNT(*), COUNT(DISTINCT ...)
|
||||
- **Dimensions:** группировки
|
||||
- **Filters:** фильтры
|
||||
|
||||
+3
-2
@@ -95,8 +95,9 @@ Kafka → ClickHouse → BI).
|
||||
|
||||
- **Аудитория:** продвинутые менти, прошедшие базовую программу. Пишем обобщённо,
|
||||
но затачиваем под реальный первый прогон, а не под гипотетических будущих менти.
|
||||
- **Режим:** самостоятельный, асинхронный. Менти клонирует репозиторий, поднимает
|
||||
стенд у себя (`make up`) и идёт по урокам из `docs/course/` рядом с кодом.
|
||||
- **Режим:** самостоятельный, асинхронный. Менти клонирует репозиторий, готовит
|
||||
стенд штатным путём (`make generated-history-analytics && make up`) и идёт по
|
||||
урокам из `docs/course/` рядом с кодом.
|
||||
Уроки короткие и односоставные — ожидаемый срок прохождения одного **около дня**.
|
||||
- **Роль ментора:** еженедельный созвон-сверка (покрывает несколько уроков), без
|
||||
построчного разбора кода.
|
||||
|
||||
@@ -310,7 +310,7 @@ Native filters создаются в `build_dashboard_metadata`. Там есть
|
||||
- `Browser` по `browser_name`.
|
||||
|
||||
Эти фильтры задаются в левой панели dashboard. Click-to-filter между виджетами не включен:
|
||||
клик по сектору pie chart, карте, строке таблицы или funnel не меняет остальные charts.
|
||||
клик по сектору pie chart, столбцу Top Countries, строке таблицы или funnel не меняет остальные charts.
|
||||
|
||||
Фильтр применяется только к charts, где есть нужное поле. `Country`, `Device Type` и
|
||||
`Browser` работают с charts на `dm.v_events_enriched`; агрегированные витрины для UTM,
|
||||
|
||||
@@ -32,8 +32,9 @@
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Не модернизируем **типы** виджетов (`pie`/`world_map`/`dist_bar` → ECharts) —
|
||||
отдельный косметический заход.
|
||||
- Не модернизируем **типы** виджетов (`pie`/геовизуализация/`dist_bar` → ECharts) —
|
||||
отдельный косметический заход. Геоблок позже заменён задачей 10
|
||||
`generator-model-time-startup-history`.
|
||||
- Не трогаем эмодзи в тайтлах, секции-заголовки, языковой винегрет.
|
||||
- Не трогаем генератор.
|
||||
- Не правим код `create_dashboard.py` в рамках этой спеки — это реализация.
|
||||
@@ -60,7 +61,7 @@ geo_country: 40 | device_type: 2 (Mobile/Computer) | utm_source: 5 | utm_medium:
|
||||
| Avg Events/Session | big_number_total | оставить, переименовать `/Visit` |
|
||||
| Top Pages | dist_bar | **апгрейд в Funnel** (центральный учебный объект) |
|
||||
| UTM Effectiveness | table | оставить; **выкинуть колонки purchases/add_to_cart** (всегда 0) |
|
||||
| Geography Map | world_map | оставить (40 стран; тип модернизировать отдельно) |
|
||||
| Geography Map | прежняя геовизуализация | позже заменена на `Top Countries by Events` |
|
||||
| Traffic by Device | pie | оставить |
|
||||
| Events by Hour | line | **проверить на пустоту**, иначе дропнуть |
|
||||
| Data Quality Summary | dist_bar | оставить (⚠️ позже пересмотрено — см. ниже) |
|
||||
|
||||
Reference in new issue
Block a user