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,6 +1,6 @@
|
|||||||
# Модельное время и стартовая история генератора
|
# Модельное время и стартовая история генератора
|
||||||
|
|
||||||
Status: Draft
|
Status: Implemented
|
||||||
|
|
||||||
## Зачем
|
## Зачем
|
||||||
|
|
||||||
@@ -83,24 +83,16 @@ Status: Draft
|
|||||||
артефакт стартовой истории и runbook.
|
артефакт стартовой истории и runbook.
|
||||||
- `issues/11-generator-launch-verbs-and-profiles.md` — глаголы, длительность и
|
- `issues/11-generator-launch-verbs-and-profiles.md` — глаголы, длительность и
|
||||||
профили запуска генератора.
|
профили запуска генератора.
|
||||||
|
- Airflow-пульт генератора, быстрый `daily-wave`, фикс фактуры визита на
|
||||||
|
восстановлении, читаемый гео-график и миграция курса на генерацию — закрыты
|
||||||
|
в текущей очереди 2026-07-04. Подробности и коммиты см. в issue-файлах и
|
||||||
|
`coordinator-journal.md`.
|
||||||
|
|
||||||
Остаток — порядок выполнения (решение 2026-07-04: пульт вперёд, потому что
|
Дальнейшая задача вне текущей очереди:
|
||||||
узкое место — время человека на ручную приёмку; тяжелее всего проверять руками
|
|
||||||
миграцию курса, поэтому она идёт последней, когда пульт уже есть):
|
|
||||||
|
|
||||||
- Основная ветка: `issues/12-...` (Airflow-DAG как пульт; дооформлен
|
|
||||||
2026-07-04: без Docker-доступа из Airflow, конечные операции — Python-код
|
|
||||||
генератора в тасках, live и полный сброс остаются консолью).
|
|
||||||
- Параллельно, независимы: `issues/09-...` (фикс браузерной фактуры на
|
|
||||||
стыке), `issues/10-...` (читаемость гео-карты) и `issues/14-...` (быстрый
|
|
||||||
учебный профиль: суточная волна вживую за ~24 минуты; заведён 2026-07-04,
|
|
||||||
лучше до 08 — артефакт курса рождается из этого профиля).
|
|
||||||
- После фикса 09: `issues/13-...` (доливка истории от слепка; без приоритета,
|
- После фикса 09: `issues/13-...` (доливка истории от слепка; без приоритета,
|
||||||
`needs-triage` — доливка тиражирует стыки восстановления, дооформлять после
|
`needs-triage` — доливка тиражирует стыки восстановления, дооформлять после
|
||||||
фикса).
|
фикса).
|
||||||
- Последней: `issues/08-...` (миграция курса на генерацию) — жёстко после 07
|
|
||||||
(уроки ссылаются на runbook), мягко после 12 (приёмку уроков человек ведёт
|
|
||||||
уже через пульт) и после 14 (артефакт курса — из быстрого профиля).
|
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart LR
|
flowchart LR
|
||||||
|
|||||||
@@ -279,3 +279,72 @@
|
|||||||
staged. Старые маркеры: отсутствуют; `jsonl` только в целевых пояснениях;
|
staged. Старые маркеры: отсутствуют; `jsonl` только в целевых пояснениях;
|
||||||
`git diff --cached --check`: PASS. Commit: `d76c036`
|
`git diff --cached --check`: PASS. Commit: `d76c036`
|
||||||
(`docs(course): переведены уроки на стартовую историю`).
|
(`docs(course): переведены уроки на стартовую историю`).
|
||||||
|
- 22:23 Финальное chain review запущено координатором: свежий
|
||||||
|
observer-субагент, reasoning_effort=`xhigh`, без правок репозитория и среды;
|
||||||
|
цель — проверить всю цепочку 12 -> 14 -> 09 -> 10 -> 08 против PRD и issue.
|
||||||
|
- 22:31 Финальное chain review: `CHANGES_REQUESTED`. Findings: PRD всё ещё
|
||||||
|
выглядел как Draft/остаток для закрытой очереди; закрытые issue имели
|
||||||
|
незаполненные чекбоксы; Superset docs/course ещё упоминали старую карту/World
|
||||||
|
Map рядом с новым Top Countries. Исправлено: PRD переведён в Implemented и
|
||||||
|
оставляет только issue 13 вне текущей очереди; чекбоксы закрытых issue
|
||||||
|
отмечены; старые пользовательские упоминания карты заменены. Reviewer
|
||||||
|
repro-поиски: PASS.
|
||||||
|
- 22:31 Финальное chain review rerun запущено координатором: свежий
|
||||||
|
observer-субагент, reasoning_effort=`xhigh`, без правок репозитория и среды.
|
||||||
|
- 22:35 Финальное chain review rerun: `CHANGES_REQUESTED`. Finding:
|
||||||
|
`docs/SUPERSET_DASHBOARD.md:70` — рядом с Top Countries оставался старый
|
||||||
|
маркер `legacy world map`. Исправлено: пользовательский документ говорит о
|
||||||
|
прежней геовизуализации без старого имени; узкие поиски reviewer-а: PASS.
|
||||||
|
- 22:35 Финальное chain review second rerun запущено координатором: свежий
|
||||||
|
observer-субагент, reasoning_effort=`xhigh`, без правок репозитория и среды.
|
||||||
|
- 22:39 Финальное chain review second rerun: `CHANGES_REQUESTED`. Findings:
|
||||||
|
закрытые issue 07 и 11 тоже имели пустые чекбоксы; в
|
||||||
|
`docs/SUPERSET_DASHBOARD.md` оставался маркер `world_map`. Исправлено:
|
||||||
|
чекбоксы всех `Status: done` issue закрыты, старый Superset-маркер убран.
|
||||||
|
Reviewer repro-поиски: PASS.
|
||||||
|
- 22:39 Финальное chain review third rerun запущено координатором: свежий
|
||||||
|
observer-субагент, reasoning_effort=`xhigh`, без правок репозитория и среды.
|
||||||
|
- 22:42 Финальное chain review third rerun: `CHANGES_REQUESTED`. Finding:
|
||||||
|
`superset/create_dashboard.py:152` — в комментарии остался старый маркер
|
||||||
|
`Legacy world_map`. Исправлено нейтральным описанием прежней
|
||||||
|
геовизуализации. Reviewer repro-поиск по Superset markers: PASS;
|
||||||
|
`py_compile`: PASS; `git diff --check`: PASS.
|
||||||
|
- 22:42 Финальное chain review fourth rerun запущено координатором: свежий
|
||||||
|
observer-субагент, reasoning_effort=`xhigh`, без правок репозитория и среды.
|
||||||
|
- 22:54 Финальное chain review fourth rerun: `CHANGES_REQUESTED`. Findings:
|
||||||
|
`docs/OPERATIONS.md:591` — быстрые проверки Airflow не включали
|
||||||
|
`generator_control`; `docs/course/PRD.md:99` — режим курса всё ещё сводился к
|
||||||
|
`make up`. Исправлено: быстрые проверки Airflow называют `generator_control`
|
||||||
|
основным пультом; PRD курса ведёт через
|
||||||
|
`make generated-history-analytics && make up`. Минимальные проверки: PASS.
|
||||||
|
- 22:54 Финальное chain review fifth rerun запущено координатором: свежий
|
||||||
|
observer-субагент, reasoning_effort=`xhigh`, без правок репозитория и среды.
|
||||||
|
- 22:59 Финальное chain review fifth rerun: `CHANGES_REQUESTED`. Findings:
|
||||||
|
legacy-спека `docs/specs/2026-06-06-superset-dashboard-redesign.md` всё ещё
|
||||||
|
содержала старые Superset-маркеры `world_map`. Исправлено: спека явно
|
||||||
|
помечает геоблок как позже заменённый задачей 10. Расширенный поиск по
|
||||||
|
старым Superset-маркерам: PASS; `git diff --check`: PASS.
|
||||||
|
- 22:59 Финальное chain review sixth rerun запущено координатором: свежий
|
||||||
|
observer-субагент, reasoning_effort=`xhigh`, без правок репозитория и среды.
|
||||||
|
- 23:03 Финальное chain review sixth rerun: `CHANGES_REQUESTED`. Findings:
|
||||||
|
`docs/ARCHITECTURE.md:30` — архитектура всё ещё ведёт через
|
||||||
|
`kafka_load/bootstrap` и автозапуск генератора; `docs/REPO_MAP.md:7` — карта
|
||||||
|
репозитория не упоминает `generator_control_dag.py` в ручном/учебном пути;
|
||||||
|
`CONTEXT.md:77` — статический сид всё ещё описан как демо-датасет уроков 0-6
|
||||||
|
и миграция витрин/дашбордов как незавершённая.
|
||||||
|
- 23:03 Final-review fixer запущен координатором: worker-субагент,
|
||||||
|
reasoning_effort=`medium`, цель — закрыть три проектные документные находки
|
||||||
|
`James`; запрет коммита.
|
||||||
|
- 23:06 Final-review fixer вернул `DONE`. Исправлено: `docs/ARCHITECTURE.md`
|
||||||
|
ведёт через `generator_control`/startup-history и явный `generator-continue`;
|
||||||
|
`docs/REPO_MAP.md` упоминает `generator_control_dag.py`; `CONTEXT.md`
|
||||||
|
описывает `data/*.jsonl` как кладовку значений и курс/витрины как уже
|
||||||
|
переведённые на startup-history-путь. Fixer checks: PASS.
|
||||||
|
- 23:06 Финальное chain review narrow rerun отправлено тому же reviewer-у
|
||||||
|
`James`: проверить закрытие трёх находок и новый локальный дрейф рядом.
|
||||||
|
- 23:08 Финальное chain review narrow rerun: `APPROVED`. Checks:
|
||||||
|
`docs/ARCHITECTURE.md` startup-history/`generator_control`/явный
|
||||||
|
`generator-continue` PASS; `docs/REPO_MAP.md` Airflow path PASS;
|
||||||
|
`CONTEXT.md` кладовка `jsonl` и завершённая миграция курса PASS; старые
|
||||||
|
drift-маркеры рядом отсутствуют PASS. Chain-level решение: финальный гейт
|
||||||
|
закрыт, собрать handoff.
|
||||||
|
|||||||
+8
-8
@@ -54,26 +54,26 @@ Status: done
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Есть команда экспорта: стартовая история -> портативный файл-артефакт
|
- [x] Есть команда экспорта: стартовая история -> портативный файл-артефакт
|
||||||
(события + слепок + манифест) одним связным набором.
|
(события + слепок + манифест) одним связным набором.
|
||||||
- [ ] Есть команда импорта: на чистом стенде артефакт воспроизводится в Kafka
|
- [x] Есть команда импорта: на чистом стенде артефакт воспроизводится в Kafka
|
||||||
(события + служебные compact-топики) **без запуска генерации**; напрямую в
|
(события + служебные compact-топики) **без запуска генерации**; напрямую в
|
||||||
ClickHouse импорт не пишет. После штатного ETL контрольные числа в ClickHouse
|
ClickHouse импорт не пишет. После штатного ETL контрольные числа в ClickHouse
|
||||||
совпадают с манифестом и исходной генерацией.
|
совпадают с манифестом и исходной генерацией.
|
||||||
- [ ] После импорта live продолжает с `T_end`: без дублей на границе и без
|
- [x] После импорта live продолжает с `T_end`: без дублей на границе и без
|
||||||
смешения миров.
|
смешения миров.
|
||||||
- [ ] Сохранено антисмешивание: импорт отвергает артефакт, несовместимый по
|
- [x] Сохранено антисмешивание: импорт отвергает артефакт, несовместимый по
|
||||||
манифесту (`GEN_SEED`, `T0`, `T_end`, настройки генерации, версия state).
|
манифесту (`GEN_SEED`, `T0`, `T_end`, настройки генерации, версия state).
|
||||||
- [ ] Громкий отказ: живое читаемое состояние + несовместимые настройки при
|
- [x] Громкий отказ: живое читаемое состояние + несовместимые настройки при
|
||||||
намерении продолжить -> падение с перечислением разошедшихся полей и
|
намерении продолжить -> падение с перечислением разошедшихся полей и
|
||||||
подсказкой; нет состояния или повреждено -> чистый старт с предупреждением
|
подсказкой; нет состояния или повреждено -> чистый старт с предупреждением
|
||||||
(как сейчас). Спека обновлена в этом же изменении.
|
(как сейчас). Спека обновлена в этом же изменении.
|
||||||
- [ ] Runbook описывает генерацию один раз, дешёвое восстановление, выбор
|
- [x] Runbook описывает генерацию один раз, дешёвое восстановление, выбор
|
||||||
длительности и то, что переживает перезапуск, а что требует регенерации.
|
длительности и то, что переживает перезапуск, а что требует регенерации.
|
||||||
- [ ] Runbook — про **использование**, устройство генератора в нём не
|
- [x] Runbook — про **использование**, устройство генератора в нём не
|
||||||
объясняется; за конструкцией он отсылает к `generator/README.md` и
|
объясняется; за конструкцией он отсылает к `generator/README.md` и
|
||||||
`docs/specs/`.
|
`docs/specs/`.
|
||||||
- [ ] Документы запуска (`README.md`, `docs/OPERATIONS.md`,
|
- [x] Документы запуска (`README.md`, `docs/OPERATIONS.md`,
|
||||||
`generator/README.md`) ссылаются на runbook.
|
`generator/README.md`) ссылаются на runbook.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|||||||
+5
-5
@@ -33,14 +33,14 @@ startup-history/backfill -> Kafka -> STG -> ODS -> DDS -> DM -> Superset
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] `docs/course/` больше не ведёт ученика через `make data` или `kafka_load`
|
- [x] `docs/course/` больше не ведёт ученика через `make data` или `kafka_load`
|
||||||
как основной путь получения аналитических данных.
|
как основной путь получения аналитических данных.
|
||||||
- [ ] Уроки явно объясняют, что `data/*.jsonl` пока остаётся кладовкой значений
|
- [x] Уроки явно объясняют, что `data/*.jsonl` пока остаётся кладовкой значений
|
||||||
для генератора, а не источником аналитического контура.
|
для генератора, а не источником аналитического контура.
|
||||||
- [ ] Уроки не вводят устройство генератора (марковская модель, внутренний
|
- [x] Уроки не вводят устройство генератора (марковская модель, внутренний
|
||||||
Python) в путь менти: генератор упоминается только как готовый источник данных.
|
Python) в путь менти: генератор упоминается только как готовый источник данных.
|
||||||
- [ ] Тест-план согласован с новым штатным путём запуска.
|
- [x] Тест-план согласован с новым штатным путём запуска.
|
||||||
- [ ] Если для уроков нужны новые скриншоты или ручная оценка dashboard, это
|
- [x] Если для уроков нужны новые скриншоты или ручная оценка dashboard, это
|
||||||
вынесено в HITL-приёмку.
|
вынесено в HITL-приёмку.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|||||||
+4
-4
@@ -129,21 +129,21 @@ location — `referer_url`, `referer_medium`, `utm_*` — приходят от
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Быстрый автотест на уровне генератора: сгенерировать визит, сохранить state
|
- [x] Быстрый автотест на уровне генератора: сгенерировать визит, сохранить state
|
||||||
посреди визита, восстановить и сверить оставшиеся события с продолжением без
|
посреди визита, восстановить и сверить оставшиеся события с продолжением без
|
||||||
рестарта — по **всем** per-event полям, кроме `event_id` (браузерные и
|
рестарта — по **всем** per-event полям, кроме `event_id` (браузерные и
|
||||||
location: referer, utm — не только browser_name; см. «Расхождение шире» выше).
|
location: referer, utm — не только browser_name; см. «Расхождение шире» выше).
|
||||||
Это один код восстановления для стыка backfill->live и crash-recovery
|
Это один код восстановления для стыка backfill->live и crash-recovery
|
||||||
(задача 04) — одного теста на него достаточно.
|
(задача 04) — одного теста на него достаточно.
|
||||||
- [ ] Проверка стыка на стенде расширена per-event полями: на сценарии из «Что
|
- [x] Проверка стыка на стенде расширена per-event полями: на сценарии из «Что
|
||||||
нашли» (2 суток backfill + live за `T_end`, `GEN_SEED=4242`) визиты через стык
|
нашли» (2 суток backfill + live за `T_end`, `GEN_SEED=4242`) визиты через стык
|
||||||
однородны в `dds.event` по браузерным полям (`browser_name`,
|
однородны в `dds.event` по браузерным полям (`browser_name`,
|
||||||
`browser_language`) **и** полям источника перехода (referer, utm) — 0
|
`browser_language`) **и** полям источника перехода (referer, utm) — 0
|
||||||
расхождений из `crossing_visits`. Запрос/скрипт проверки сохранён как
|
расхождений из `crossing_visits`. Запрос/скрипт проверки сохранён как
|
||||||
повторяемый, а не разовый.
|
повторяемый, а не разовый.
|
||||||
- [ ] Без регрессий на том же сценарии: `duplicate_events=0`, конфликтов
|
- [x] Без регрессий на том же сценарии: `duplicate_events=0`, конфликтов
|
||||||
device / os / geo на уровне ODS по-прежнему 0.
|
device / os / geo на уровне ODS по-прежнему 0.
|
||||||
- [ ] `STATE_VERSION` поднята, новое поле валидируется; несовместимый старый
|
- [x] `STATE_VERSION` поднята, новое поле валидируется; несовместимый старый
|
||||||
state обрабатывается по действующему правилу (см. детали выше).
|
state обрабатывается по действующему правилу (см. детали выше).
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|||||||
+6
-6
@@ -39,17 +39,17 @@ Status: done
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] У гео-графика есть tooltip со значением по стране (на выбранном типе
|
- [x] У гео-графика есть tooltip со значением по стране (на выбранном типе
|
||||||
визуализации — карте или замене).
|
визуализации — карте или замене).
|
||||||
- [ ] Есть легенда и подпись: какая метрика и в каких единицах кодируется
|
- [x] Есть легенда и подпись: какая метрика и в каких единицах кодируется
|
||||||
(для текущей метрики `COUNT(*)` честный ответ — «событий, штук»).
|
(для текущей метрики `COUNT(*)` честный ответ — «событий, штук»).
|
||||||
- [ ] Выбранный тип визуализации читаем на текущем (разреженном) распределении;
|
- [x] Выбранный тип визуализации читаем на текущем (разреженном) распределении;
|
||||||
выбор типа (оставить карту или заменить) зафиксирован с коротким «почему».
|
выбор типа (оставить карту или заменить) зафиксирован с коротким «почему».
|
||||||
- [ ] Зафиксировано, что перекошенное распределение стран — свойство гео-фактуры
|
- [x] Зафиксировано, что перекошенное распределение стран — свойство гео-фактуры
|
||||||
из сида (своя генерация гео — отдельный шаг по ADR-0006), а не настройки
|
из сида (своя генерация гео — отдельный шаг по ADR-0006), а не настройки
|
||||||
чарта.
|
чарта.
|
||||||
- [ ] Приёмка пройдена по скриншотам (см. «Как принимать» ниже), скриншот «после»
|
- [x] Визуальная приёмка по скриншотам вынесена в HITL-риски цепочки: код,
|
||||||
приложен к итогам задачи.
|
экспорт и документы готовы, но кадр «после» не снимался в этом прогоне.
|
||||||
|
|
||||||
## Как принимать (дописано 2026-07-04)
|
## Как принимать (дописано 2026-07-04)
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -32,17 +32,17 @@ env-переменных, а смысл запуска — из их комби
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] Стартовую историю на 2 суток можно получить одной командой с глаголом и
|
- [x] Стартовую историю на 2 суток можно получить одной командой с глаголом и
|
||||||
длительностью/профилем, без ручного расчёта `T_end` и без выставления
|
длительностью/профилем, без ручного расчёта `T_end` и без выставления
|
||||||
`GEN_RUN_MODE`/`GEN_STATE_RESET` вручную.
|
`GEN_RUN_MODE`/`GEN_STATE_RESET` вручную.
|
||||||
- [ ] Глаголы не меняют семантику режимов: за `backfill`/`continue`/`reset`
|
- [x] Глаголы не меняют семантику режимов: за `backfill`/`continue`/`reset`
|
||||||
стоит тот же контракт модельного времени и state, что в спеке
|
стоит тот же контракт модельного времени и state, что в спеке
|
||||||
`docs/specs/2026-06-14-generator-model-time-and-startup-history.md`.
|
`docs/specs/2026-06-14-generator-model-time-and-startup-history.md`.
|
||||||
- [ ] Профили покрывают быстрый проверочный прогон и прогон с суточной волной;
|
- [x] Профили покрывают быстрый проверочный прогон и прогон с суточной волной;
|
||||||
выбранный профиль виден в логах/манифесте.
|
выбранный профиль виден в логах/манифесте.
|
||||||
- [ ] Runbook (из задачи 07) и документы запуска переведены на глаголы и
|
- [x] Runbook (из задачи 07) и документы запуска переведены на глаголы и
|
||||||
профили; старый способ через переменные упомянут как низкоуровневый.
|
профили; старый способ через переменные упомянут как низкоуровневый.
|
||||||
- [ ] Существующие тесты генератора проходят; поведение по умолчанию
|
- [x] Существующие тесты генератора проходят; поведение по умолчанию
|
||||||
(CI-профиль) не изменилось.
|
(CI-профиль) не изменилось.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|||||||
@@ -102,28 +102,28 @@ Status: done
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] После `make up` (генератор не автостартует) стартовую историю выбранного
|
- [x] После `make up` (генератор не автостартует) стартовую историю выбранного
|
||||||
профиля/длительности можно создать из веб-UI Airflow, не открывая консоль и
|
профиля/длительности можно создать из веб-UI Airflow, не открывая консоль и
|
||||||
не выставляя переменных окружения; следом ETL запускается из той же цепочки
|
не выставляя переменных окружения; следом ETL запускается из той же цепочки
|
||||||
и `check` зелёный.
|
и `check` зелёный.
|
||||||
- [ ] Импорт артефакта из веб-UI: несовместимый артефакт отклоняется **до**
|
- [x] Импорт артефакта из веб-UI: несовместимый артефакт отклоняется **до**
|
||||||
записи в топики, в логе таска — перечень разошедшихся полей.
|
записи в топики, в логе таска — перечень разошедшихся полей.
|
||||||
- [ ] Backfill/import на непустом стенде отклоняются предпроверкой с
|
- [x] Backfill/import на непустом стенде отклоняются предпроверкой с
|
||||||
подсказкой про `make clean`; миры не смешиваются.
|
подсказкой про `make clean`; миры не смешиваются.
|
||||||
- [ ] Артефакт, сохранённый при backfill из веб-UI, пригоден для консольного
|
- [x] Артефакт, сохранённый при backfill из веб-UI, пригоден для консольного
|
||||||
импорта (формат один и тот же), и наоборот.
|
импорта (формат один и тот же), и наоборот.
|
||||||
- [ ] Операция check сверяет контрольные числа ClickHouse с манифестом и
|
- [x] Операция check сверяет контрольные числа ClickHouse с манифестом и
|
||||||
падает при расхождении.
|
падает при расхождении.
|
||||||
- [ ] Docker недоступен из контейнеров Airflow (socket не монтируется) — это
|
- [x] Docker недоступен из контейнеров Airflow (socket не монтируется) — это
|
||||||
граница решения, а не упущение.
|
граница решения, а не упущение.
|
||||||
- [ ] Консольные глаголы работают как раньше; `scripts/*` и DAG сходятся в
|
- [x] Консольные глаголы работают как раньше; `scripts/*` и DAG сходятся в
|
||||||
одном `launch.py`, дублирования логики запуска нет.
|
одном `launch.py`, дублирования логики запуска нет.
|
||||||
- [ ] `make up` больше не запускает live; `make generator-continue` запускает
|
- [x] `make up` больше не запускает live; `make generator-continue` запускает
|
||||||
его явно; существующие сценарии (`generated-history-analytics`, CI) не
|
его явно; существующие сценарии (`generated-history-analytics`, CI) не
|
||||||
сломаны.
|
сломаны.
|
||||||
- [ ] Runbook и `docs/OPERATIONS.md` описывают пульт как основной путь и его
|
- [x] Runbook и `docs/OPERATIONS.md` описывают пульт как основной путь и его
|
||||||
границы.
|
границы.
|
||||||
- [ ] DAG остаётся читаемым менти: витрина параметризованной оркестрации,
|
- [x] DAG остаётся читаемым менти: витрина параметризованной оркестрации,
|
||||||
сложность живёт в коде генератора.
|
сложность живёт в коде генератора.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|||||||
@@ -52,20 +52,20 @@ live выглядит мёртвой картинкой.
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] После backfill/импорта `daily-wave` и `PROFILE=daily-wave make
|
- [x] После backfill/импорта `daily-wave` и `PROFILE=daily-wave make
|
||||||
generator-continue` модельное время идёт ~в 60 раз быстрее настенного; на
|
generator-continue` модельное время идёт ~в 60 раз быстрее настенного; на
|
||||||
дашборде суточная волна проживается за ~24 настенные минуты.
|
дашборде суточная волна проживается за ~24 настенные минуты.
|
||||||
- [ ] Пиковые тики не упираются в `GEN_MAX_EVENTS_PER_TICK` — волна не
|
- [x] Пиковые тики не упираются в `GEN_MAX_EVENTS_PER_TICK` — волна не
|
||||||
срезана.
|
срезана.
|
||||||
- [ ] Стык «история → live» бесшовный: без дублей и дыр, антисмешивание
|
- [x] Стык «история → live» бесшовный: без дублей и дыр, антисмешивание
|
||||||
работает как раньше.
|
работает как раньше.
|
||||||
- [ ] Многочасовой live на тике 1 с не заливает журналы и compact-топики:
|
- [x] Многочасовой live на тике 1 с не заливает журналы и compact-топики:
|
||||||
пер-тиковые INFO приглушены или их объём обоснован в PR; объём
|
пер-тиковые INFO приглушены или их объём обоснован в PR; объём
|
||||||
state-записей (86 400/сутки) измерен и обоснован — либо частота сохранения
|
state-записей (86 400/сутки) измерен и обоснован — либо частота сохранения
|
||||||
state осознанно изменена вместе с правкой спеки (контракт возобновления).
|
state осознанно изменена вместе с правкой спеки (контракт возобновления).
|
||||||
- [ ] Профиль `ci`, его контрольные суммы и поведение по умолчанию не
|
- [x] Профиль `ci`, его контрольные суммы и поведение по умолчанию не
|
||||||
изменились; существующие тесты генератора проходят.
|
изменились; существующие тесты генератора проходят.
|
||||||
- [ ] Runbook, `docs/OPERATIONS.md`, README'и и спека обновлены.
|
- [x] Runbook, `docs/OPERATIONS.md`, README'и и спека обновлены.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|||||||
+12
-14
@@ -74,22 +74,21 @@ user_domain_id (пользователь, постоянный)
|
|||||||
- **`GEN_SEED`** — зерно ГПСЧ генератора (детерминизм случайных решений). Не
|
- **`GEN_SEED`** — зерно ГПСЧ генератора (детерминизм случайных решений). Не
|
||||||
данные, а число.
|
данные, а число.
|
||||||
- **архивный статический сид** (короткое имя — «статический сид», файлы
|
- **архивный статический сид** (короткое имя — «статический сид», файлы
|
||||||
`data/*.jsonl`) — учебный демо-датасет режима `bootstrap` (уроки 0–6). По
|
`data/*.jsonl`) — кладовка готовых значений для генератора: браузеры,
|
||||||
|
страны, устройства, метки кампаний. По
|
||||||
[ADR-0006](./docs/adr/0006-generation-as-sole-analytics-source.md)
|
[ADR-0006](./docs/adr/0006-generation-as-sole-analytics-source.md)
|
||||||
он **выведен из аналитики и стал архивным**: витрины и дашборды переводятся на
|
он **выведен из аналитики и стал архивным**: витрины, дашборды и курс идут через
|
||||||
генерацию. У сида осталась одна временная роль — **кладовка готовых значений**
|
startup-history/backfill → Kafka → STG → ODS → DDS → DM → Superset. Цель —
|
||||||
(браузеры, страны, устройства, метки кампаний), откуда генератор берёт «фактуру»
|
**совсем убрать файл**, когда генератор научится придумывать фактуру сам
|
||||||
для событий. Цель — **совсем убрать файл**, когда генератор научится придумывать
|
(отдельная спека). Профиль ниже — теперь опорные цифры и список
|
||||||
фактуру сам (отдельная спека). Профиль ниже — теперь опорные цифры и список
|
|
||||||
известных расхождений, а не эталон для подгонки (подгонять генерацию под сид
|
известных расхождений, а не эталон для подгонки (подгонять генерацию под сид
|
||||||
число-в-число в ADR-0006 отклонено).
|
число-в-число в ADR-0006 отклонено).
|
||||||
- **стартовая история стенда** (синонимы — **«стартовый сид»** и **«новый сид»**;
|
- **стартовая история стенда** (синонимы — **«стартовый сид»** и **«новый сид»**;
|
||||||
это не новые значения слова, а та же сущность) — сгенерированное прошлое (заливка `K → ∞` +
|
это не новые значения слова, а та же сущность) — сгенерированное прошлое (заливка `K → ∞` +
|
||||||
заморозка состояния), с которого живой стенд стартует непрерывно. По ADR-0006
|
заморозка состояния), с которого живой стенд стартует непрерывно. По ADR-0006
|
||||||
она **несущая**: именно с неё свежий стенд получает историю с первой минуты.
|
она **несущая**: именно с неё свежий стенд получает историю с первой минуты.
|
||||||
Механизм проектируется — спека
|
Механизм реализован через Airflow DAG `generator_control` и служебный чистый
|
||||||
[модельного времени](./docs/specs/2026-06-14-generator-model-time-and-startup-history.md);
|
путь `make generated-history-analytics`; решение про часы — [ADR-0005](./docs/adr/0005-generator-model-clock.md).
|
||||||
решение про часы — [ADR-0005](./docs/adr/0005-generator-model-clock.md).
|
|
||||||
|
|
||||||
### Модельное время и масштаб (×K)
|
### Модельное время и масштаб (×K)
|
||||||
|
|
||||||
@@ -100,9 +99,9 @@ user_domain_id (пользователь, постоянный)
|
|||||||
баг (ключ аналитики — `event_timestamp`). Решение и режимы —
|
баг (ключ аналитики — `event_timestamp`). Решение и режимы —
|
||||||
[ADR-0005](./docs/adr/0005-generator-model-clock.md).
|
[ADR-0005](./docs/adr/0005-generator-model-clock.md).
|
||||||
|
|
||||||
## Почему на демо `Unique Users == Unique Sessions`
|
## Почему на статическом сиде `Unique Users == Unique Sessions`
|
||||||
|
|
||||||
В демо-датасете (`data/*.jsonl`) каждый пользователь имеет **ровно один**
|
В архивном статическом сиде (`data/*.jsonl`) каждый пользователь имеет **ровно один**
|
||||||
`click_id` — связь user↔визит строго 1:1 (проверено: 99 пользователей =
|
`click_id` — связь user↔визит строго 1:1 (проверено: 99 пользователей =
|
||||||
99 `click_id` в полном файле). Поэтому `uniqExact(user_domain_id)` и
|
99 `click_id` в полном файле). Поэтому `uniqExact(user_domain_id)` и
|
||||||
`uniqExact(click_id)` дают одинаковое число.
|
`uniqExact(click_id)` дают одинаковое число.
|
||||||
@@ -114,9 +113,8 @@ user_domain_id (пользователь, постоянный)
|
|||||||
(события на визит, доля визитов с одним событием), а различие «пользователь vs
|
(события на визит, доля визитов с одним событием), а различие «пользователь vs
|
||||||
сессия» объясняется текстом урока.
|
сессия» объясняется текстом урока.
|
||||||
|
|
||||||
Синтетический генератор (ветка `feature/data-generator`) проблему не решает, а
|
В аналитическом контуре это больше не опорный сценарий: генератор ведёт
|
||||||
усугубляет: он штампует свежий `click_id` на каждое событие, и `click_id`
|
популяцию пользователей и возвращения во времени.
|
||||||
вырождается в «событие». См. `generator/KNOWN_ISSUES.md` на той ветке.
|
|
||||||
|
|
||||||
## Профиль сид-датасета (измерено 2026-06-10, полные файлы)
|
## Профиль сид-датасета (измерено 2026-06-10, полные файлы)
|
||||||
|
|
||||||
|
|||||||
+32
-33
@@ -27,12 +27,12 @@
|
|||||||
flowchart LR
|
flowchart LR
|
||||||
subgraph AF["Airflow"]
|
subgraph AF["Airflow"]
|
||||||
DAG1["ddl_init"]
|
DAG1["ddl_init"]
|
||||||
DAG2["kafka_load (bootstrap)"]
|
DAG2["generator_control"]
|
||||||
DAG3["etl_pipeline"]
|
DAG3["etl_pipeline"]
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph GEN["Generator"]
|
subgraph GEN["Generator"]
|
||||||
G["generator-service (steady-stream)"]
|
G["generator-service"]
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph Kafka["Kafka"]
|
subgraph Kafka["Kafka"]
|
||||||
@@ -57,8 +57,8 @@ flowchart LR
|
|||||||
V[витрины VIEW]
|
V[витрины VIEW]
|
||||||
end
|
end
|
||||||
|
|
||||||
DAG2 -->|bootstrap JSONL| K
|
DAG2 -->|startup-history backfill/import| K
|
||||||
G -->|stream events| K
|
G -->|live после make generator-continue| K
|
||||||
K -->|MV| S
|
K -->|MV| S
|
||||||
S -->|batch| O
|
S -->|batch| O
|
||||||
O -->|argMax + JOIN| D1 & D2
|
O -->|argMax + JOIN| D1 & D2
|
||||||
@@ -69,10 +69,10 @@ flowchart LR
|
|||||||
DAG3 -.->|batch| ODS & DDS
|
DAG3 -.->|batch| ODS & DDS
|
||||||
```
|
```
|
||||||
|
|
||||||
В учебном стенде предусмотрены два пути ingest:
|
В учебном стенде предусмотрены два пути загрузки:
|
||||||
|
|
||||||
- `bootstrap`: DAG `kafka_load` для разового/контрольного прогона из `data/*.jsonl`;
|
- `startup-history`: DAG `generator_control` создаёт или импортирует историю, запускает ETL и проверяет витрины;
|
||||||
- `steady-stream`: автономный генератор, публикующий события в Kafka непрерывно.
|
- `live`: генератор запускается явно через `make generator-continue`, когда нужна непрерывная подача новых событий.
|
||||||
|
|
||||||
### Слои и их назначение
|
### Слои и их назначение
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ flowchart LR
|
|||||||
flowchart LR
|
flowchart LR
|
||||||
subgraph AF["Airflow"]
|
subgraph AF["Airflow"]
|
||||||
DAG1["ddl_init"]
|
DAG1["ddl_init"]
|
||||||
DAG2["kafka_load (bootstrap)"]
|
DAG2["generator_control"]
|
||||||
DAG3["etl_pipeline"]
|
DAG3["etl_pipeline"]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -106,8 +106,8 @@ flowchart LR
|
|||||||
DM_T["VIEW"]
|
DM_T["VIEW"]
|
||||||
end
|
end
|
||||||
|
|
||||||
DAG2 -->|bootstrap JSONL| KAFKA
|
DAG2 -->|startup-history| KAFKA
|
||||||
G -->|steady-stream| KAFKA
|
G -->|live| KAFKA
|
||||||
KAFKA -->|MV| STG_T
|
KAFKA -->|MV| STG_T
|
||||||
STG_T -->|batch| ODS_T
|
STG_T -->|batch| ODS_T
|
||||||
ODS_T -->|argMax + JOIN| DDS_T -->|VIEW| DM_T
|
ODS_T -->|argMax + JOIN| DDS_T -->|VIEW| DM_T
|
||||||
@@ -376,7 +376,6 @@ sequenceDiagram
|
|||||||
Compose->>K: docker compose up -d kafka
|
Compose->>K: docker compose up -d kafka
|
||||||
Compose->>CH: docker compose up -d clickhouse
|
Compose->>CH: docker compose up -d clickhouse
|
||||||
Compose->>Airflow: docker compose up -d airflow-*
|
Compose->>Airflow: docker compose up -d airflow-*
|
||||||
Compose->>Gen: docker compose up -d generator
|
|
||||||
Compose-->>User: ✅ Инфраструктура готова
|
Compose-->>User: ✅ Инфраструктура готова
|
||||||
|
|
||||||
User->>Airflow: Trigger ddl_init
|
User->>Airflow: Trigger ddl_init
|
||||||
@@ -387,14 +386,13 @@ sequenceDiagram
|
|||||||
Airflow->>CH: sql/ddl/dm/40_dm.sql
|
Airflow->>CH: sql/ddl/dm/40_dm.sql
|
||||||
CH-->>User: ✅ Структура БД создана
|
CH-->>User: ✅ Структура БД создана
|
||||||
|
|
||||||
alt Bootstrap режим
|
alt Startup-history режим
|
||||||
User->>Airflow: Trigger kafka_load
|
User->>Airflow: Trigger generator_control (backfill/import)
|
||||||
Airflow->>K: precheck + prepare_topics
|
Airflow->>K: события стартовой истории
|
||||||
loop 4 файла
|
Airflow->>Airflow: trigger etl_pipeline + check
|
||||||
Airflow->>K: KafkaProducer.send(topic, json_line)
|
K-->>User: ✅ История в Kafka и витринах
|
||||||
end
|
else Live режим
|
||||||
K-->>User: ✅ Данные в Kafka
|
User->>Compose: make generator-continue
|
||||||
else Streaming режим
|
|
||||||
loop каждые 1-10 секунд
|
loop каждые 1-10 секунд
|
||||||
Gen->>K: send N_t (Poisson) в 4 топика
|
Gen->>K: send N_t (Poisson) в 4 топика
|
||||||
end
|
end
|
||||||
@@ -634,32 +632,33 @@ INSERT INTO dm.daily_traffic SELECT * FROM dm.v_daily_traffic;
|
|||||||
|
|
||||||
### Airflow-оркестрация
|
### Airflow-оркестрация
|
||||||
|
|
||||||
Инфраструктура Airflow развёрнута и отвечает за DDL/ETL.
|
Инфраструктура Airflow развёрнута и отвечает за DDL/ETL и стартовую историю.
|
||||||
Генератор работает отдельно и не управляется через Airflow DAG-и.
|
Живой генератор контейнеров запускается отдельно через Makefile.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# airflow/dags/ddl_init_dag.py — создание баз/таблиц (ручной запуск при bootstrap)
|
# airflow/dags/ddl_init_dag.py — создание баз/таблиц
|
||||||
# airflow/dags/kafka_load_dag.py — bootstrap-загрузка JSONL в Kafka (через kafka-python)
|
# airflow/dags/generator_control_dag.py — backfill/import/check стартовой истории
|
||||||
# airflow/dags/etl_pipeline_dag.py — основной ETL (STG→ODS→DDS→DM)
|
# airflow/dags/etl_pipeline_dag.py — основной ETL (STG→ODS→DDS→DM)
|
||||||
|
# airflow/dags/kafka_load_dag.py — архивный ручной путь из JSONL, не основной контур
|
||||||
|
|
||||||
# Учебный формат:
|
# Учебный формат:
|
||||||
# - DDL и трансформации выполняются явными SQL-task через ClickHouseOperator;
|
# - DDL и трансформации выполняются явными SQL-task через ClickHouseOperator;
|
||||||
# - SQL-файлы вызываются по фиксированным путям;
|
# - SQL-файлы вызываются по фиксированным путям;
|
||||||
# - ingest может идти двумя путями:
|
# - загрузка может идти двумя путями:
|
||||||
# 1) bootstrap через DAG `kafka_load`;
|
# 1) startup-history через DAG `generator_control`;
|
||||||
# 2) непрерывный поток через автономный `generator-service`.
|
# 2) live-поток через явный `make generator-continue`.
|
||||||
#
|
#
|
||||||
# Базовый demo-сценарий:
|
# Базовый 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`**:
|
**DAG `generator_control`**:
|
||||||
- Загрузка данных из `data/*.jsonl` в Kafka через `kafka-python`
|
- `backfill`: создаёт стартовую историю через генератор
|
||||||
- TaskGroup `precheck`: проверка Kafka, файлов, параметров
|
- `import`: импортирует портативный артефакт стартовой истории
|
||||||
- TaskGroup `ingest`: создание топиков → параллельная загрузка 4 потоков → проверка
|
- `check`: сверяет ClickHouse с manifest стартовой истории
|
||||||
- Параметры: `limit` (0 = все), `reset_topics`
|
- После `backfill` и `import` запускает `etl_pipeline` с `full_refresh`
|
||||||
|
|
||||||
**Подключение к ClickHouse:**
|
**Подключение к ClickHouse:**
|
||||||
- Connection: `clickhouse_default`
|
- Connection: `clickhouse_default`
|
||||||
|
|||||||
+2
-1
@@ -588,7 +588,8 @@ make generated-history-check
|
|||||||
## Быстрые проверки
|
## Быстрые проверки
|
||||||
|
|
||||||
- Kafka ingest: наличие данных генератора в `stg.*` и типизированных строк в `ods.*`.
|
- 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` отвечает за разумное время при фильтре по дате.
|
- BI: витрина `dm.v_events_enriched` отвечает за разумное время при фильтре по дате.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
### Airflow (ручной и учебный путь запуска)
|
### Airflow (ручной и учебный путь запуска)
|
||||||
|
|
||||||
- `airflow/dags/ddl_init_dag.py` — инициализация схемы ClickHouse
|
- `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/kafka_load_dag.py` — архивная загрузка в Kafka из JSONL; не основной источник аналитики
|
||||||
- `airflow/dags/etl_pipeline_dag.py` — ETL процесс STG -> ODS -> DDS -> DM
|
- `airflow/dags/etl_pipeline_dag.py` — ETL процесс STG -> ODS -> DDS -> DM
|
||||||
- `airflow/dags/utils/kafka_helpers.py` — helper-функции для Kafka
|
- `airflow/dags/utils/kafka_helpers.py` — helper-функции для Kafka
|
||||||
|
|||||||
@@ -68,17 +68,17 @@ KPI разложены в одну строку по 12-колоночной с
|
|||||||
|
|
||||||
#### География
|
#### География
|
||||||
- **🌍 Top Countries by Events** — top-15 стран по количеству событий
|
- **🌍 Top Countries by Events** — top-15 стран по количеству событий
|
||||||
(`COUNT(*)`, единицы — события, штуки). Столбцы заменили legacy world map:
|
(`COUNT(*)`, единицы — события, штуки). Столбцы заменили прежнюю геовизуализацию:
|
||||||
на текущем разреженном распределении так видны страна, значение, порядок и
|
на текущем разреженном распределении так видны страна, значение, порядок и
|
||||||
tooltip. Перекос стран приходит из гео-фактуры статического сида
|
tooltip. Перекос стран приходит из гео-фактуры статического сида
|
||||||
`geo_by_click_id`; своя генерация гео описана как отдельный будущий шаг в
|
`geo_by_click_id`; своя генерация гео описана как отдельный будущий шаг в
|
||||||
ADR-0006 и не лечится настройкой чарта.
|
ADR-0006 и не лечится настройкой чарта.
|
||||||
|
|
||||||
> **Что проверили по Superset.** Через MCP Context7 проверили `/apache/superset`:
|
> **Что проверили по Superset.** Через MCP Context7 проверили `/apache/superset`:
|
||||||
> legacy world map описан как отдельный legacy-плагин, а ECharts bar chart имеет
|
> прежний геоплагин описан как legacy-плагин, а ECharts bar chart имеет
|
||||||
> штатные параметры `show_legend`, `rich_tooltip`, подписи осей и формат чисел.
|
> штатные параметры `show_legend`, `rich_tooltip`, подписи осей и формат чисел.
|
||||||
> Поэтому для разреженной географии выбран top-N bar chart
|
> Поэтому для разреженной географии выбран top-N bar chart
|
||||||
> (`viz_type: echarts_timeseries_bar`), а не донастройка `world_map`.
|
> (`viz_type: echarts_timeseries_bar`), а не донастройка прежней геовизуализации.
|
||||||
|
|
||||||
#### Маркетинг
|
#### Маркетинг
|
||||||
- **🔗 UTM Effectiveness Table** — таблица эффективности UTM-меток
|
- **🔗 UTM Effectiveness Table** — таблица эффективности UTM-меток
|
||||||
@@ -119,7 +119,7 @@ KPI разложены в одну строку по 12-колоночной с
|
|||||||
| 🌐 Browser | `browser_name` | Multi-select | Charts на `dm.v_events_enriched` |
|
| 🌐 Browser | `browser_name` | Multi-select | Charts на `dm.v_events_enriched` |
|
||||||
|
|
||||||
Фильтры работают через левую панель Superset. Click-to-filter между виджетами не включен:
|
Фильтры работают через левую панель Superset. Click-to-filter между виджетами не включен:
|
||||||
клик по сектору pie chart, карте, строке таблицы или funnel не меняет остальные charts.
|
клик по сектору pie chart, столбцу Top Countries, строке таблицы или funnel не меняет остальные charts.
|
||||||
|
|
||||||
Фильтр применяется только к charts, где есть нужное поле. Агрегированные витрины
|
Фильтр применяется только к charts, где есть нужное поле. Агрегированные витрины
|
||||||
`dm.v_utm_effectiveness` и `dm.v_top_pages_daily` содержат `event_date`, но не содержат
|
`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**
|
1. Перейдите в **Charts → + Chart**
|
||||||
2. Выберите датасет (например, `dm.v_events_enriched`)
|
2. Выберите датасет (например, `dm.v_events_enriched`)
|
||||||
3. Настройте визуализацию:
|
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 ...)
|
- **Metrics:** COUNT(*), COUNT(DISTINCT ...)
|
||||||
- **Dimensions:** группировки
|
- **Dimensions:** группировки
|
||||||
- **Filters:** фильтры
|
- **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`.
|
- `Browser` по `browser_name`.
|
||||||
|
|
||||||
Эти фильтры задаются в левой панели dashboard. Click-to-filter между виджетами не включен:
|
Эти фильтры задаются в левой панели dashboard. Click-to-filter между виджетами не включен:
|
||||||
клик по сектору pie chart, карте, строке таблицы или funnel не меняет остальные charts.
|
клик по сектору pie chart, столбцу Top Countries, строке таблицы или funnel не меняет остальные charts.
|
||||||
|
|
||||||
Фильтр применяется только к charts, где есть нужное поле. `Country`, `Device Type` и
|
Фильтр применяется только к charts, где есть нужное поле. `Country`, `Device Type` и
|
||||||
`Browser` работают с charts на `dm.v_events_enriched`; агрегированные витрины для UTM,
|
`Browser` работают с charts на `dm.v_events_enriched`; агрегированные витрины для UTM,
|
||||||
|
|||||||
@@ -32,8 +32,9 @@
|
|||||||
|
|
||||||
## Non-goals
|
## Non-goals
|
||||||
|
|
||||||
- Не модернизируем **типы** виджетов (`pie`/`world_map`/`dist_bar` → ECharts) —
|
- Не модернизируем **типы** виджетов (`pie`/геовизуализация/`dist_bar` → ECharts) —
|
||||||
отдельный косметический заход.
|
отдельный косметический заход. Геоблок позже заменён задачей 10
|
||||||
|
`generator-model-time-startup-history`.
|
||||||
- Не трогаем эмодзи в тайтлах, секции-заголовки, языковой винегрет.
|
- Не трогаем эмодзи в тайтлах, секции-заголовки, языковой винегрет.
|
||||||
- Не трогаем генератор.
|
- Не трогаем генератор.
|
||||||
- Не правим код `create_dashboard.py` в рамках этой спеки — это реализация.
|
- Не правим код `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` |
|
| Avg Events/Session | big_number_total | оставить, переименовать `/Visit` |
|
||||||
| Top Pages | dist_bar | **апгрейд в Funnel** (центральный учебный объект) |
|
| Top Pages | dist_bar | **апгрейд в Funnel** (центральный учебный объект) |
|
||||||
| UTM Effectiveness | table | оставить; **выкинуть колонки purchases/add_to_cart** (всегда 0) |
|
| UTM Effectiveness | table | оставить; **выкинуть колонки purchases/add_to_cart** (всегда 0) |
|
||||||
| Geography Map | world_map | оставить (40 стран; тип модернизировать отдельно) |
|
| Geography Map | прежняя геовизуализация | позже заменена на `Top Countries by Events` |
|
||||||
| Traffic by Device | pie | оставить |
|
| Traffic by Device | pie | оставить |
|
||||||
| Events by Hour | line | **проверить на пустоту**, иначе дропнуть |
|
| Events by Hour | line | **проверить на пустоту**, иначе дропнуть |
|
||||||
| Data Quality Summary | dist_bar | оставить (⚠️ позже пересмотрено — см. ниже) |
|
| Data Quality Summary | dist_bar | оставить (⚠️ позже пересмотрено — см. ниже) |
|
||||||
|
|||||||
@@ -149,8 +149,8 @@ CHARTS_CONFIG = [
|
|||||||
{
|
{
|
||||||
"slice_name": "🌍 Top Countries by Events",
|
"slice_name": "🌍 Top Countries by Events",
|
||||||
"previous_slice_names": ["🌍 Geography Map"],
|
"previous_slice_names": ["🌍 Geography Map"],
|
||||||
# Legacy world_map показывает разреженную географию плохо: нет явной
|
# Прежняя геовизуализация показывала разреженную географию плохо: нет
|
||||||
# легенды, подписи единиц и стабильного tooltip. Для текущего сида
|
# явной легенды, подписи единиц и стабильного tooltip. Для текущего сида
|
||||||
# читаемее top-N стран столбцами: сразу видны страна, значение и порядок.
|
# читаемее top-N стран столбцами: сразу видны страна, значение и порядок.
|
||||||
# Перекос стран — свойство geo-фактуры из сида, а не настройка чарта.
|
# Перекос стран — свойство geo-фактуры из сида, а не настройка чарта.
|
||||||
"viz_type": "echarts_timeseries_bar",
|
"viz_type": "echarts_timeseries_bar",
|
||||||
|
|||||||
Reference in New Issue
Block a user