[2026-10-15] eagle: personal/projects/balda/balda.md personal/projects/balda/execution-broker.md personal/projects/balda/setup.md work/projects/cpm-telemetry-data-requirements-2026-10-15.md

This commit is contained in:
Alexey Martemyanov committed 2026-10-15 21:19:53 +06:00
1 parent f40e56c89d
commit 88062a62bf
4 files changed
+114 -6

No files matched your search

@@ -0,0 +1,108 @@
---
title: CPM — что нужно в данных (требования к телеметрии из гипотез)
date: '2026-10-15'
tags:
- work
- cpm
- telemetry
---
# CPM: что нужно в данных
Внутренняя заметка. **Цифры из ClickHouse, в публичные PR/комментарии не переносить.** Контекст: [[cpm-readiness-telemetry-tech-design-2026-10-15]], [[cpm-web-extension-data-analysis-summary-2026-10-08]], [[cpm-web-extension-code-guide-2026-10-09]]. PR: telemetry #7376 → #7384 → #7385; harness #7378 → fix A #7379 → fix B #7381.
## Метод
- Окно: 2026-10-12…14 UTC (3 полных дня), версии с диагностикой: iOS 7.240+, macOS 1.210+. Единица: `daily`-пиксель = устройство-день на причину, не пользователь и не эпизод.
- Инструмент: `~/Developer/grafana-data-tools` (`query.py`, Grafana → ClickHouse `metrics.pixels`, read-only). Запросы ниже запускались через тот же helper (`read-dashboard.py`) отдельным раннером; SQL приведён в конце.
- Классификация когорт по приоритету: error 6 → нет background view → tab not connected → Network заменён → пробуждение (view <30 с после `dealloc`) → недавняя загрузка контекста (`load`/`base_url_changed` ≤2 мин) → other.
## Объёмы (12–14 октября)
| | iOS | macOS |
|---|---|---|
| `initialization_failed.daily` | 3 273 025 | 119 950 |
| `stuck.daily` | 511 660 | 40 842 |
| восстановились без reload (daily, `from=initialization_failed`) | 1 135 477 (34.7% от init) | 30 738 (25.6%) |
| stuck → восстановились после M4 reload (daily) | 293 557 (57.4% от stuck) | 21 865 (53.5%) |
| `reload_failed.daily` | 140 921 (27.5% от stuck) | 17 796 (43.6%) |
`initialization_failed` — только `.daily`; `stuck`, `recovered_*`, `reload_failed` — `daily`+`count`. Параметры снимка есть только на init_failed и stuck; на recovered только `recovery_from`/`recovery_document`/`recovery_after`.
## Когорты: доля init → stuck
| Когорта | iOS init → stuck | macOS init → stuck |
|---|---|---|
| error 6 | 6.1% → 21.5% | 1.0% → 1.9% |
| нет background view | 48.1% → 10.9% | 3.3% → 1.8% |
| tab not connected | 0.03% → 0.05% | 6.2% → 8.9% |
| Network заменён | 16.8% → 39.7% | 13.6% → 26.6% |
| пробуждение (view <30 с) | 7.9% → 9.5% | 32.5% → 32.2% |
| недавняя загрузка контекста | 15.7% → 6.0% | 20.0% → 6.4% |
| other | 5.3% → 12.5% | 23.4% → 22.2% |
Рост доли при переходе init → stuck значит, что когорта чаще остаётся сломанной (error 6, Network заменён, tab not connected); падение значит самоизлечение (нет view, недавняя загрузка).
## Основание для фиксов
- **B (Network-процесс)**: когорта «Network заменён» растёт в 2–2.4× при переходе в stuck; `reload_failed` высок (reload расширения не лечит мёртвый worker). Основание сильное. Ограничение: `network_restarted` это прокси «PID изменился»; причинность подтверждает только `init_stage=none` (#7385).
- **A (первая загрузка посреди сессии)**: сигнатура «загрузка ≤2 мин, не при запуске (launch age ≥15 мин), первый view»: iOS 129k init (3.9%) → 4.6k stuck (0.9%); macOS 505 → 118. Реально, но разово (0.23×) и на macOS мелко. Сигнатура неточна: захватывает и M4-reload; нужен `context_load_cause`.
## Паттерны событий без фиксов (stuck.daily, 14 октября, хвост `bg_events` без возрастов)
| Картина | Хвост | iOS / macOS (строк) | Чем различать |
|---|---|---|---|
| **P1. Цикл пробуждения**: idle-выгрузка, затем view | `view>proxy_on>dealloc>view>proxy_on` | 16.0k / 4.3k (wake) + 16.3k / 2.4k (то же, но view старше 30 с, класс other) | медленный старт или потеря: `bg_ready_after`, `bg_view_age`, `init_stage`, `recovery_after`; базлайн здоровых пробуждений (#7384) |
| **P2. Цикл «пробуждение → error 6»** | `proxy_on>dealloc>view>proxy_on>error_E:6` (23.6k), повторяется `error>dealloc>view>proxy_on>error` (5.7k), после `died_crash` (1.5k) | iOS; macOS 118 | `bg_load_error_after` (бакет 25–35 с = таймер 30 с), `bg_load_error_app_state`, `bg_view_creations` |
| **P3. Контекст загружен, view не создан** | `load` или `load>base_url_changed` | 17.1k + 0.9k / 162 + 81 | `bg_ready_after=none`, `context_load_age`, мелкие корзины `app_launch_age`, `app_state`, время загрузка→view из #7384 |
| **P4. Первая загрузка: `load>view>proxy_on`** | | 6.8k + 2.3k / 570 | `context_load_cause`, `bg_view_creations=1`; эффект A измерять `first_load_wait` |
| **P5. Фон выгружен в момент сбоя** (хвост на `dealloc`) | `proxy_on>dealloc>view>proxy_on>dealloc` | 1.9k / 494 | `bg_view_alive=false` (уже есть), `bg_ready_after`, `bg_view_age` |
| **P6. macOS: вкладка без расширения** | `load>view>proxy_on>dealloc`, часто с `extension_updated` | iOS ≈0 / 627 + 235 | есть `tab_controller_match`, `tab_has_ext_scripts`, `app_version_change`, `reason` |
В iOS-когорте «нет view» крупнейшие группы лежат в первых 30 с после запуска: восстановление сессии (около половины) и `reason=other`. Первая корзина `app_launch_age` «<30 с» слишком грубая.
## Что нужно в данных (минимум)
| Поле / пиксель | Вопрос | Где |
|---|---|---|
| `bg_ready_after` | всё ещё загружается, загрузился или упал | PR0 |
| `bg_view_age` | пробуждение или давно | PR0 |
| `bg_load_error_after`, `bg_load_error_app_state` (только при error 6) | таймер 30 с, состояние приложения | PR0 |
| `recovery_document`, `recovery_after` | опоздавший ответ или потерянный | PR0 |
| `app_state`, `open_tabs` (грубо), только на `initialization_failed` | когорта «нет view» на запуске | PR0 |
| **новое:** `context_load_cause` (запуск / установка / апгрейд / reload при восстановлении) и `context_load_age` | точная сигнатура A, замена `load@` и `extension_updated` | PR0 |
| **новое:** `bg_died_reason`, `base_url_changed` | смерть процесса, очистка при смене baseURL | PR0 |
| **новое:** мелкие корзины `app_launch_age` для первых 30 с | гонка на запуске | PR0 |
| **новое на stuck:** `stuck_after` | сколько от первого сбоя до stuck | PR0 |
| `init_stage` | дошёл ли init до background | #7385 (срочно) |
| `cpm_background_ready_{context_load,wake}` | базлайн здоровых загрузок и пробуждений | #7384 |
| `background_restart` (причина, исход), `first_load_wait` | эффект фиксов B и A | удержанная ветка |
| убрать | `loading_tabs`; в таймлайне `view`, `dealloc`, `proxy_on`, `error_*`, `hold/release/proxy_off` | |
### `bg_events`
- Сейчас единственный источник давности загрузки и причины смерти процесса. Остальные токены дублируют `bg_view_creations`, `context_errors` или нули (`hold/release/proxy_off` = 0%).
- Скаляры вместо таймлайна воспроизводят когорты загрузки и пробуждения на 100% строк (измерено 14 октября).
- Однодневная уникальность строк `stuck.daily` по всем параметрам: с `bg_events` 8.3% (iOS) и 30% (macOS); сокращённые информативные токены 2.1% / 5.2%; скаляры 0.96% / 4.4%; без событий 0.25% / 2.0%.
- Верхняя граница прироста от новых полей (синтетическое независимое равновероятное поле): с текущим `bg_events` при десяти значениях iOS 21%, macOS 65%; со скалярами 3.6% / 15.8%. Про «не станет хуже» можно говорить только со скалярами. В публичный PR цифры не писать.
## Критерии успеха и опровержения
- **B** подтверждается, если после релиза падают доля «Network заменён» среди stuck и `reload_failed`, `background_restart` показывает восстановление, а у таких stuck `init_stage=none`.
- **A** подтверждается, если сокращается когорта «мид-сессионная первая загрузка» (`context_load_cause`). Если нет, основание слабое: она около 1% stuck на iOS и почти 0 на macOS.
- Остаток P1/P3 подтверждает гипотезу «медленный старт, а не потеря», если `bg_ready_after` у упавших заметно хуже базлайна здоровых загрузок и `recovery_document=failed_navigation`.
## SQL (классификация; даты подставлять)
```sql
-- stuck.daily / init_failed.daily; приоритет когорт
multiIf(
errs LIKE '%ContextErrorDomain:6%', '1_error6',
creations = '0', '2_no_background_view',
scripts = 'false', '3_tab_not_connected',
net = 'true', '4_network_replaced',
has(ev,'view@30s') AND arrayExists(x -> startsWith(x,'dealloc@'), ev), '5_wake_view_lt30s',
arrayExists(x -> x IN ('load@30s','load@1m','load@2m','base_url_changed@30s','base_url_changed@1m','base_url_changed@2m'), ev), '6_context_load_recent',
'7_other')
-- параметры: network_restarted, context_errors, bg_view_creations, tab_has_ext_scripts, bg_events (decodeURLComponent)
```