Files
clickstream-ch-kafka-supers…/CONTEXT.md
T
ddadminandClaude Opus 4.8 1dd79a3287 docs(course): лабы 07 (next-day) и 08 (continue) + метадокументы (#22)
Зачем: два новых режима роста мира не имели уроков, а метадокументы
курса не знали о новом маршруте.

Что: лаба 07 «Следующий день и границы времени» — инкремент дня,
сверка manifest, переходящие визиты запросом в dds.event, включение
расписания на один запуск, цена роста full_refresh; лаба 08 «Живой
поток и свежесть данных» — расслоение свежести слоёв, стоп/продолжение
генератора, users < sessions, врезка про модельное время; LEARNING_PLAN
и README курса согласованы с маршрутом 0–8; в CONTEXT.md починена
ссылка «урок 7» (теперь ведёт на врезку лабы 08). Числа со стенда
помечены маркером «сверить-на-стенде».

Проверка: обе лабы по шаблону LESSON_STANDARD (6 секций, явный «верни
как было»); внутренние ссылки разрешаются; git diff --check чистый.

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

13 KiB
Raw Blame History

CONTEXT.md — глоссарий домена

Доменный язык стенда: как мы называем сущности кликстрима и что под ними понимаем. Один термин — одно имя. Ведётся вместе с docs/adr/ (см. ADR-0001).

Сущности

Пользователь (user)

user_domain_id (UUID) — постоянный идентификатор пользователя (cookie-уровень), переживает отдельные визиты. Источник — device_events, привязан к click_id. В витринах: uniqExact(user_domain_id).

Визит / сессия (visit / session)

click_id (UUID) — визит: envelope из одного и более событий с общим контекстом device/geo. В DDL dds.click описана как «контекст сессии пользователя» (см. sql/ddl/dds/30_dds.sql).

Важно: в источнике нет отдельного session-таймаута (как Snowplow domain_sessionid). Поэтому в этой модели сессия ≡ визит ≡ click_id — группа событий под одним идентификатором, а не окно активности по тайм-ауту. Если в будущем понадобится «настоящая» сессия по 30-минутному окну неактивности — это отдельная производная над user_domain_id + event_ts, и на сиде она дала бы другие группы: в полном сиде 11 внутрисессионных пауз превышают 30 минут, а разброс времени внутри click_id доходит до 49 минут (см. профиль сид-датасета ниже; ранее здесь ошибочно значилось «разброс ≤ 1 мин» — это был замер по малому срезу файла).

«Сессию» и «визит» используем как синонимы; в UI предпочитаем «визит», когда важно подчеркнуть, что это не сессия-по-тайм-ауту.

Событие (event)

event_id (UUID) — отдельное действие пользователя в рамках визита: pageview, click, purchase, add_to_cart и т.п. (поле event_type). Источник — browser_events + location_events. В витринах: count().

Иерархия

user_domain_id  (пользователь, постоянный)
  └── click_id  (визит/сессия — 1..N событий с общим device/geo)
        └── event_id  (событие: pageview / click / purchase ...)

Здоровые данные дают пирамиду users ≤ sessions ≤ events.

Термины потоковой генерации (steady-stream)

Относятся к синтетическому потоку из генератора (режим steady-stream), не к статическому сиду. Решение и контекст — ADR-0004, форма доработки — спека генератора.

Популяция пользователей (user population)

Множество пользователей с постоянными user_domain_id, которые генератор держит во времени и из которых разыгрывает активность. В отличие от сида (где пул user_domain_id плоский и 1:1 с визитами), популяция — это источник возвратов: один и тот же пользователь порождает несколько визитов.

Возвращающийся пользователь (returning user)

Пользователь, открывающий более одного визита (click_id) во времени, с межсессионными паузами. Именно возвраты дают расхождение users < sessions — то, чего нет на сиде (users == sessions) и что отличает поток от статики.

Три значения слова «сид»

Слово перегружено — в разговоре про генератор это три разные сущности, их нельзя путать (см. ADR-0005):

  • GEN_SEED — зерно ГПСЧ генератора (детерминизм случайных решений). Не данные, а число.
  • архивный статический сид (короткое имя — «статический сид», файлы data/*.jsonl) — кладовка готовых значений для генератора: браузеры, страны, устройства, метки кампаний. По ADR-0006 он выведен из аналитики и стал архивным: витрины, дашборды и курс идут через startup-history/backfill → Kafka → STG → ODS → DDS → DM → Superset. Цель — совсем убрать файл, когда генератор научится придумывать фактуру сам (отдельная спека). Профиль ниже — теперь опорные цифры и список известных расхождений, а не эталон для подгонки (подгонять генерацию под сид число-в-число в ADR-0006 отклонено).
  • стартовая история стенда (синонимы — «стартовый сид» и «новый сид»; это не новые значения слова, а та же сущность) — сгенерированное прошлое (заливка K → ∞ + заморозка состояния), с которого живой стенд стартует непрерывно. По ADR-0006 она несущая: именно с неё свежий стенд получает историю с первой минуты. Механизм реализован через Airflow DAG world_init и служебный чистый путь make generated-history-analytics; решение про часы — ADR-0005.

Мир (стенда)

Совокупное состояние данных стенда: события в Kafka, слои ClickHouse, состояние генератора (модельные часы, живая популяция) и manifest с контрольными числами. «Вырастить мир» — добавить в него модельное время (next-day или живой поток), «восстановить мир» — залить его из артефакта.

Эталонный мир (reference world)

Канонический стартовый мир менти: 3 модельных дня на профиле daily-wave, собран мейнтейнером один раз, хранится сжатым артефактом в git. Все менти импортируют один и тот же файл — числа в лабах воспроизводимы число-в-число. Решение — спека редизайна пути менти.

Три режима менти

import (база: загрузить эталонный мир) и две ветки от восстановленного состояния: next-day (пакетно добавить модельный день) и continue (живой поток от той же границы). Это разные педагогики и разные лабы; backfill — не режим менти, а инструмент мейнтейнера для сборки эталонного мира. См. ту же спеку.

Модельное время и масштаб (×K)

Модельное время стенда отвязано от настенных часов: генератор крутит внутренние часы, а драйвер задаёт скорость — ×1 (как реальное время), ×K (ускоренно, учебная ручка в лабе 08) или K → ∞ (мгновенная заливка прошлого). При ускорении «сейчас» стенда уходит вперёд настенного времени — это свойство, не баг (ключ аналитики — event_timestamp). Решение и режимы — ADR-0005.

Почему на статическом сиде Unique Users == Unique Sessions

В архивном статическом сиде (data/*.jsonl) каждый пользователь имеет ровно один click_id — связь user↔визит строго 1:1 (проверено: 99 пользователей = 99 click_id в полном файле). Поэтому uniqExact(user_domain_id) и uniqExact(click_id) дают одинаковое число.

Это свойство конкретного датасета, а не закон модели и не баг расчёта. В реальных данных пользователь возвращается несколькими визитами, и числа расходятся. Поэтому на дашборде мы не показываем две одинаковые KPI-плитки (это читалось бы как ошибка) — вместо дубля идут производные метрики (события на визит, доля визитов с одним событием), а различие «пользователь vs сессия» объясняется текстом урока.

В аналитическом контуре это больше не опорный сценарий: генератор ведёт популяцию пользователей и возвращения во времени.

Профиль сид-датасета (измерено 2026-06-10, полные файлы)

Опорные цифры о статическом сиде (data/*.jsonl) — для калибровки генератора и проверки гипотез. Измерено по полным файлам (1000 событий); внимание: ранние оценки «1..7 событий на визит» делались по малому срезу и неверны.

  • Объём: 1000 событий, 99 визитов (click_id), 99 пользователей (1:1).
  • Длина визита: 1..27 событий, медиана 10, среднее 10.1.
  • Паузы между событиями визита: медиана ~20 с, p95 ≈ 17 мин, максимум ≈ 40 мин; пауз длиннее 30 минут — 11 штук. Разброс времени внутри одного click_id — до 49 минут.
  • Воронка: 25% визитов достигают /confirmation. Пути — с петлями: возвраты на /home, просмотр обоих товаров; у 21 из 25 «купивших» визитов есть события после /confirmation, у 9 — /confirmation встречается дважды. То есть /confirmation — последний шаг воронки, но не обязательно последнее событие визита.
  • Страницы (по событиям): /home 426, /product_a 236, /product_b 157, /cart 93, /payment 53, /confirmation 35. event_type — 100% pageview.

Слои данных

STG → ODS → DDS → DM — см. docs/ARCHITECTURE.md. Сейчас витрины (dm.*) и дашборд Superset строятся на статическом сиде. По ADR-0006 целевой источник аналитики — генерация (стартовая история и живой поток); перевод загрузки, витрин и дашбордов на неё входит в текущую работу, детальный план — отдельной спекой.