Классификация зрителя и источника (ViewerKind / ViewSource)
Дом типизированных enum'ов, которыми dev-stats размечает каждый факт просмотра и по которым режет метрики
внимания застройщика (ADR-0057). Хранение — LowCardinality(String) в ClickHouse; wire — нижний регистр.
Назначение
Два измерения разметки просмотра объекта недвижимости:
ViewerKind— кто смотрел (тип аудитории), для сегментации «гость / агент / инвестор».ViewSource— откуда пришёл просмотр (поверхность каталога), для атрибуции трафика.
Оба проставляются консюмером при ingestion факта
(property-object-view-ended,
action-tracked) и хранятся в
property_object_view_facts; ViewerKind дополнительно —
order-компонент rollup property_object_view_daily.
Unknown-значение на входе метода → ValidationError (молчаливый дефолт запрещён).
ViewerKind (тип зрителя просмотра)
| Значение (wire) | Enum | Правило классификации |
|---|---|---|
guest | Guest | UserId == null — аноним по AnonymousId (полностью выводится из payload) |
agent | Agent | аутентифицированный зритель с ролью агента/риэлтора (по сигналу роли) |
investor | Investor | аутентифицированный зритель-инвестор (доминирующий тип аудитории каталога) |
Assumption v1: разделение Agent/Investor требует роли зрителя, которой в v1 нет ни в payload, ни в
измерениях dev-stats (реплики dim_user нет, ADR-0056). До появления сигнала роли (optional-поле
ViewerRole в событии — additive; либо реплика dim_user) аутентифицированный зритель пишется как
Investor, Agent детектируется по мере появления сигнала. Зафиксировано в «Известных ограничениях»
README.
SessionViewerKind (тип зрителя сессии)
Для session_facts применяется огрублённая пара (роль зрителя на уровне сессии
не разрешается):
| Значение (wire) | Enum | Правило |
|---|---|---|
guest | Guest | UserId == null |
user | User | UserId != null (аутентифицирован; без деления Agent/Investor) |
ViewSource (источник просмотра)
| Значение (wire) | Enum | Смысл |
|---|---|---|
catalog | Catalog | публичный каталог |
search | Search | поиск/выдача |
selection | Selection | подборка |
favorites | Favorites | избранное |
news | News | лента/новости застройщика |
direct-link | DirectLink | прямой заход по ссылке |
unknown | Unknown | источник не определён (open-факт action-tracked до closed-события) |
ViewSource несёт только property-object-view-ended; open-факт action-tracked ViewPropertyObject пишет
Unknown, авторитетное значение приходит с closed-событием (тот же PropertyObjectViewId, позже по
IngestionTime) и побеждает при argMax. ViewSource не хранится в rollup — при фильтре по нему метод
переключается на сырьё property_object_view_facts (SLO p95 ≤ 600 мс вместо ≤ 300 мс).
Порядок разрешения классификации
Классификация детерминирована: тот же факт при переигрывании получает ту же метку. Разрешение — по первому совпавшему правилу сверху вниз.
ViewerKind (просмотр):
| Приоритет | Условие | Результат |
|---|---|---|
| 1 | UserId == null | Guest |
| 2 | UserId != null и есть сигнал роли «агент/риэлтор» | Agent |
| 3 | UserId != null без сигнала роли (v1: сигнала нет) | Investor (дефолт аутентифицированного — Assumption v1) |
ViewSource (просмотр): для closed-факта — значение из метаданных action; для open-факта — Unknown;
при склейке open/closed побеждает closed (позже по IngestionTime). Unknown wire-значение из closed-payload →
Unknown + warning (fallback контракта на ingestion, не ValidationError).
Связь ViewerKind → SessionViewerKind (огрубление на уровне сессии): сессионный факт не разрешает
роль зрителя, поэтому Agent и Investor схлопываются в User:
ViewerKind просмотра | SessionViewerKind сессии |
|---|---|
Guest | Guest |
Agent | User |
Investor | User |
Обработка неизвестных значений (ingestion vs вход метода)
Одно и то же unknown-значение обрабатывается по-разному в зависимости от того, где оно появилось:
| Место | Enum | Поведение при unknown | Почему |
|---|---|---|---|
| Ingestion (payload события) | ViewSource | → Unknown + warning (не DLQ) | producer мог добавить значение; факт сохраняем, размечаем как «источник не определён» |
| Ingestion (payload события) | ViewerKind | не приходит как enum — выводится консюмером (правила выше); невыводимого случая нет | классификация всегда даёт валидную метку |
| Вход метода (фильтр) | ViewerKind/ViewSource | → ValidationError (400), молчаливый дефолт запрещён | визуализатор должен явно выбирать известный сегмент |
Проверяемость
- Unknown
ViewerKind/ViewSourceво входе метода →ValidationError(не дефолт). - Open-факт с
ViewSource = Unknown, затем closed того жеPropertyObjectViewIdсCatalog→ при чтении выигрываетCatalog(argMax поIngestionTime). - Аутентифицированный зритель без сигнала роли (v1) →
Investor; тот же просмотр после появления сигнала роли агента →Agent(детерминированно от сигнала, additive). - Сессия аутентифицированного зрителя →
SessionViewerKind = Userнезависимо отAgent/Investor.
Совместимость
- Добавление нового wire-значения — breaking для клиента-визуализатора (согласовывать); unknown на входе →
ValidationError, не молчаливый дефолт. - Хранение — строкой (
LowCardinality), поэтому новое значение не ломает существующие факты.
Обратные ссылки
Автоссылки: где используется этот документ.
- Домен (CQRS) (2): Модели ответа dev-stats (типизированные ряды / точки / сводки), DevStatsFilterModel (общий вход метрик dev-stats)
- API (5): GET /api/v1/dev-stats/duration/histogram — Гистограмма длительностей просмотра, GET /api/v1/dev-stats/repeat-frequency — Повторные просмотры и частота возврата на объект, GET /api/v1/dev-stats/session-depth — Глубина сессии (объектов за сессию), GET /api/v1/dev-stats/viewers/unique — Уникальные зрители (гость/агент/инвестор), GET /api/v1/dev-stats/views/summary — Сводка просмотров (кто/сколько/как долго/как часто)
- Use Cases (1): UC-STA-001. Застройщик смотрит статистику проекта (период + проект)
- События (1): События dev-stats
- Отчёты (1): Отчет/Export: dev-stats-export (выгрузка аналитики застройщика)
- Дашборды (1): Панель Метрик Застройщика: dev-stats-overview (аналитика внимания)
- index.md (1): DevStats Service (Pin.DevStats)
- registries (1): Реестр сущностей PIN
Связанные документы
- Общий фильтр (использует оба enum'а): dev-stats-filter.md.
- Факты/rollup с этими колонками: property-object-view-facts.md, property-object-view-daily-rollup.md, session-facts.md.
- Проставление при ingestion: property-object-view-ended.md, action-tracked.md.
- ADR: ADR-0057, ADR-0056.