diff --git a/work/projects/cpm-web-extension-breakage-validation.md b/work/projects/cpm-web-extension-breakage-validation.md index 8e8bd4cc..fbcaadf5 100755 --- a/work/projects/cpm-web-extension-breakage-validation.md +++ b/work/projects/cpm-web-extension-breakage-validation.md @@ -1,28 +1,15 @@ # CPM Web Extension Breakage — статус и проверка причин -> **Текущий milestone, 2026-10-05: проверить attribution data и найти причины CPM breakage.** Исторический PR-план ниже — не текущая оценка готовности. Подробная трассировка: [[cpm-web-extension-breakage-findings]]; архитектура: [[cpm-service-worker-architecture-and-diagnostics]]. +> **Актуальный отчёт за завершённый 5 октября 2026 UTC:** [[cpm-web-extension-public-attribution-2026-10-05]]. Он сверяет все `init failure.daily`, диагностические группы, соседние события, тренды до релиза и восстановление после stuck. Исторические internal-testing проверки и PR-план ниже сохранены как архив. -## Сейчас: attribution и breakage reasons +## Текущий статус -**Граница данных.** До 2026-10-05 macOS 1.210 использовалась в internal testing примерно неделю; iOS 7.240 ещё не опубликована в App Store. macOS 1.211 / iOS 7.241 — ранние internal-сборки. Считать public incidence только по данным после начала public rollout (ожидается 2026-10-06), отдельно по платформе и версии. Internal-тесты могли специально воспроизводить failure, поэтому частоту и причинность по ним не выводим. +- Основной сигнал: 6 624 iOS и 1 405 macOS `initialization.failed.after.*.daily`; эксклюзивные группы и контрольные суммы приведены в актуальном отчёте. +- Session restoration failure сохраняется: 952 iOS / 71 macOS за 5 октября. На iOS 604 имеют scripts absent + zero background views. Долю временно восстановившихся по этому reason без связывания событий посчитать нельзя. +- M4 reload после confirmed stuck даёт 916 iOS / 354 macOS `recovered.after.extension.reload.daily` от `messaging_stuck`; это подтверждает реальные успешные ответы после reload, но не success rate всех эпизодов. +- Старые версии не содержат controller/scripts attribution. По общему тренду после macOS M1 существенный эффект tab lifecycle не выделяется. -**Что видно в attribution-bearing `debug.web.extension.cpm.messaging.stuck.*` за завершённые 2026-09-28—10-04:** - -| Версия | `.count` | `.daily` | Статус | -|---|---:|---:|---| -| macOS 1.210 | 131 | 82 | Internal testing; не оценка затронутых пользователей. | -| iOS 7.240 | 6 | 5 | До App Store release. | -| macOS 1.211 / iOS 7.241 | 0 | 0 | Включены в проверку; attributed stuck пока нет. | - -`.count` — репорты, `.daily` — дневные пиксели, не уникальные пользователи. Большой поток iOS stuck на 7.238/7.239 в основном **без** новых attribution-полей; его нельзя смешивать с 7.240. Сверка фильтров Kibana и Grafana ещё нужна. [Breakage board](https://grafana.duckduckgo.com/d/dfon7whlilnggb/cpm-weird-error-investigation?orgId=1). - -**Проверяемые сигнатуры, пока не root causes:** - -1. `bg_events`: повторный `dealloc` есть в 88/131 macOS 1.210 `.count` stuck. Internal forced-failure testing может полностью объяснять этот сигнал; он **не доказывает** естественную смерть WebContent-процесса или эффект graveyard. -2. Tab-side: в 24/131 macOS stuck отсутствуют extension scripts. В 17 из 24 `tab_controller_match=false`, хотя `tab_in_context=true`; 10 из 17 помечены `app_version_change=updated`. Гипотеза: старая/restored вкладка сохраняет прежний `webExtensionController` после создания или замены WebExtensionManager. В остальных 7 controller совпадает, но `bg_view_creations=0` (6 после update): это больше похоже на недошедший до background-view/injection startup, а не на доказанное удаление scripts. `removeAllUserScripts()` остаётся отдельной кодовой гипотезой без подтверждения этими пикселями. -3. `base_url_changed`, reload и другие причины анализировать отдельно: совпадение с stuck ещё не подтверждает причинность. - -**Следующая проверка:** на public macOS 1.210 / iOS 7.240 с 2026-10-06 раздельно считать affected daily users (recovered и permanent) против DAU той же версии; разбирать ordered `bg_events` и tab-поля по каждой сигнатуре. Воспроизвести на macOS 1.210 update/session restore и off→on Web Extensions с уже открытой вкладкой: сравнить старую и новую вкладки по controller, scripts и CPM outcome. До этого не ранжировать причины по internal `.count`. +## Исторические проверки и планы ## Как получить и проверить attribution data diff --git a/work/projects/cpm-web-extension-public-attribution-2026-10-05.md b/work/projects/cpm-web-extension-public-attribution-2026-10-05.md new file mode 100644 index 00000000..b6db90ac --- /dev/null +++ b/work/projects/cpm-web-extension-public-attribution-2026-10-05.md @@ -0,0 +1,64 @@ +# CPM Web Extension: attribution и сравнение релизов — 5 октября 2026 + +**Статус:** первый завершённый UTC-день с данными версий iOS 7.240.0 и macOS 1.210.0. Главный сигнал — `initialization.failed.after.*.daily`; `messaging.stuck.*.daily` проверен отдельно как более поздний, менее точный сигнал. Выгрузка сделана 6 октября из Grafana ClickHouse `metrics.pixels`, интервал `[2026-10-05 00:00, 2026-10-06 00:00) UTC`, `agent` и `appVersion` зафиксированы. [Dashboard](https://grafana.duckduckgo.com/d/dfon7whlilnggb/cpm-weird-error-investigation?orgId=1). + +**Вывод:** iOS session restoration по-прежнему даёт 952 первых сбоя, из них 604 со совпадающим контроллером вкладки, но без extension scripts и без созданного background view. По macOS таких первых сбоев 71, из них 12 с той же сигнатурой. Восстановление после reload наблюдается гораздо чаще, чем в предыдущих релизах; оно реально достигает успешного CPM-ответа, но долю успешных попыток эти пиксели не измеряют. Эффект исправлений tab lifecycle в совокупном тренде не выделяется. + +## 1. Охват и контрольные суммы + +| Независимые имена `.daily` пикселей | iOS 7.240 | macOS 1.210 | +|---|---:|---:| +| Первое `initialization.failed.after.*` | **6 624** | **1 405** | +| Позднее `messaging.stuck.*` | 1 440 | 489 | +| Первый неудачный post-reload CPM probe | 670 | 234 | +| CPM ответ после reload, оба `recovery_from` | 963 = 916 stuck + 47 init | 362 = 354 stuck + 8 init | +| CPM ответ без reload, `initialization_failed` | 1 555 | 353 | +| **Сумма записей CPM daily по именам пикселей** | **11 252** | **2 843** | + +Контроль: первичные события `6 624 + 1 405 = 8 029` строк в `initialization_daily.tsv`; вторичные `1 440 + 489 = 1 929` строк в `events_daily.tsv`. Суммы всех CPM daily `11 252 + 2 843 = 14 095` совпадают между `inventory.tsv` и независимым `release_cpm_daily_trends.tsv` **по каждому имени пикселя**. Включать `debug.web.extension.reload.failed.daily` в эту сумму нельзя: это отдельное семейство операций Web Extensions. Внутри CPM `initialization.failed.after.extension.reload.daily` и `messaging.extension.reload.failed.daily` обычно посылаются вместе на одной неудачной post-reload проверке: их суммы не обозначают разные эпизоды. `.daily` ограничен одним событием **на имя пикселя** за UTC-день на установку; разные имена могут относиться к одному пользователю и эпизоду. Переход версии внутри дня тоже меняет наблюдаемые суммы. Здесь нет числа уникальных пользователей, DAU той же версии и идентификатора для связывания событий. + +Публикация release tag состоялась 5 октября в 15:18 UTC для [iOS 7.240](https://github.com/duckduckgo/apple-browsers/releases/tag/7.240.0%2Bios) и 09:46 UTC для [macOS 1.210](https://github.com/duckduckgo/apple-browsers/releases/tag/1.210.0%2Bmacos). Все 6 624/1 440 iOS атрибутированных init/stuck пришли после iOS tag; у macOS 28/1 405 init и 2/489 stuck пришли до macOS tag. Пиксель не содержит канала распространения, поэтому оставшиеся записи нельзя строго отделить от internal testing. + +## 2. Первичный сигнал: группы и события рядом с `init failure.daily` + +Каждая строка попадает ровно в одну диагностическую группу по приоритету: tab scripts/controller → явные признаки background → история ошибок → неполные поля → видимо исправный native snapshot. Это **классификация снимка**, а не доказательство первопричины. Полные пересекающиеся признаки сохранены отдельно. + +| Диагностическая группа | iOS init, из 6 624 | macOS init, из 1 405 | iOS stuck, из 1 440 | macOS stuck, из 489 | +|---|---:|---:|---:|---:| +| Native snapshot без видимой ошибки | 3 717 (56,1%) | 923 (65,7%) | 789 (54,8%) | 336 (68,7%) | +| Tab attachment / injection | 931 (14,1%) | 119 (8,5%) | 53 (3,7%) | 38 (7,8%) | +| Background state | 768 (11,6%) | 165 (11,7%) | 457 (31,7%) | 35 (7,2%) | +| Только история ошибок context | 343 (5,2%) | 163 (11,6%) | 87 (6,0%) | 80 (16,4%) | +| Недостаточно tab facts | 865 (13,1%) | 35 (2,5%) | 54 (3,8%) | 0 | + +Контроль групп: iOS init `3717+931+768+343+865=6624`; macOS init `923+119+165+163+35=1405`; iOS stuck `789+53+457+87+54=1440`; macOS stuck `336+38+35+80=489`. Контроль причин первого сбоя: iOS `other 4803 + session.restoration 952 + extension.reload 670 + tab.crash 199 = 6624`; macOS `1073+71+234+27=1405`. Это `reason` навигации/эпизода, **не причина поломки**. + +**Окружающие события по главным цепочкам:** + +1. **iOS session restoration, 952.** У 604 (63,4%) `tab_controller_match=true`, scripts отсутствуют, `bg_view_creations=0`; у 607 хвост `bg_events` содержит только `load`, ещё у 283 — `load → view → proxy_on`. 754 первых сбоя попали в bucket первых 30 секунд запуска. Код ожидает начальный `loadAndSync` перед первой HTTP(S)-навигацией restored tab, но ожидание ограничено 3 секундами; неоконченная загрузка и более позднее внедрение script всё ещё способны дать временный timeout. 260 снимков уже выглядят исправно и требуют timings сообщения, а не ещё одного снимка состояния. +2. **iOS `other`, 4 803.** 2 921 выглядят исправно; 831 имеют неполные tab facts; 334 содержат background load error code 6; 239 — scripts отсутствуют при нулевом числе background views. Частые хвосты `load → view → proxy_on` (1 450) и `load → view → proxy_on → dealloc → view → proxy_on` (934). `dealloc` фиксирует освобождение background view, не падение процесса; только 85 первичных iOS строк имеют явный `died_*` в доступном хвосте. +3. **Повторная проверка после extension reload, iOS 670 / macOS 234.** Это именно первый CPM init timeout после reload, вместе с `messaging.extension.reload.failed.daily`. Типичный хвост iOS `load → base_url_changed → view → proxy_on` (483); macOS `load → base_url_changed → view → proxy_on → dealloc → view → proxy_on` (87). `base_url_changed` здесь совпадает с reload и сам по себе не доказывает ошибку URL. Native snapshot уже выглядит исправно у 470 iOS / 126 macOS; причина отсутствия ответа там не локализована. +4. **macOS `other`, 1 073.** 722 выглядят исправно, 138 не имеют живого background view, 115 имеют только историческую context error, 47 — неверный controller без scripts. За все причины init неверный controller без scripts есть у 77/1 405; в stuck — у 35/489. App update сам по себе не сохраняет старый `WKWebView`; эти строки не доказывают сценарий «вкладка осталась у старого контроллера после обновления». Требуется событие смены manager/controller при живой вкладке. +5. **iOS `tab.crash`, 199.** 47 имеют code 6, 37 — явную смерть background процесса, 35 — scripts отсутствуют и background view не создан. Название reason означает навигацию после crash вкладки, а не установленную смерть CPM worker. + +Вторичный stuck сдвигает iOS-картину: background state 768/6 624 (11,6%) на первом сбое против 457/1 440 (31,7%) на stuck; no-scripts/zero-view 917/6 624 против 52/1 440. Это согласуется с временными startup misses и более устойчивой background-проблемой, **но это не переходная вероятность**: имена `.daily` считаются независимо. У iOS code 6 находится в 364 stuck снимках (в 363 `dealloc` раньше первой ошибки); WebKit регистрирует code 6 как `BackgroundContentFailedToLoad` после неудачной загрузки service worker. Причина отказа регистрации из пикселя неизвестна. Хвост `bg_events` ограничен 12 событиями и может обрезать старые события. «Native snapshot без видимой ошибки» означает, что текущих полей недостаточно для локализации content script → worker → native → page ответа, а не что пользовательского сбоя не было. + +## 3. Session restoration: ушли ли временные сбои? + +**Нет.** В новых версиях есть 952 iOS и 71 macOS первых `session.restoration` failures. Соответствующий поздний `stuck.session.restoration.daily` встречается 118 / 8 раз, но без связи событий нельзя сказать, какие именно первые сбои восстановились. `recovered.without.extension.reload.daily` (1 555 iOS / 353 macOS) не содержит `reason`, поэтому доля временных session-restoration эпизодов также неизвестна. + +Сравнение по имени пикселя на одинаковых пятидневных окнах после предыдущих release tags: iOS 7.238 (23–27 сентября) — 3 372 386 session restoration из 5 821 858 init daily (57,9%); iOS 7.239 (30 сентября – 4 октября) — 3 014 131 из 5 390 550 (55,9%). У iOS 7.240 за **первый неполный день** — 952 из 6 624 (14,4%). Это сильное изменение состава сигналов, совместимое с readiness gate, вошедшим в 7.240, но не оценка снижения риска на пользователя: новая версия имеет иной ранний cohort и нет DAU. macOS 1.208 (23–27 сентября) — 4 531/76 336 (5,94%); 1.209 (30 сентября – 4 октября) — 7 425/114 075 (6,51%); 1.210 за первый день — 71/1 405 (5,05%). На macOS явного снижения по этому proxy пока нет. Gate входит в macOS 1.210 / iOS 7.240 и по умолчанию включён, но фактическое состояние remote flag у отправителей не передано. + +## 4. Исправления tab lifecycle: виден ли эффект? + +[M1 tab identity fix](https://github.com/duckduckgo/apple-browsers/pull/6827) вошёл в macOS 1.209, а в 1.208 его нет; PR менял только macOS. Старые версии не посылали новые поля controller/scripts, поэтому сравним лишь общий proxy `stuck.other.daily / initialization.failed.after.other.daily`, **не частоту tab bugs**. В сопоставимых пятидневных окнах он равен 27 493/69 565 = **39,52%** на macOS 1.208 и 40 030/103 135 = **38,81%** на 1.209. Изменение на 0,71 процентного пункта мало и может отражать состав cohort/нагрузки; это не измеренный эффект фикса. Новый 1.210 за один день даёт 420/1 073 = **39,14%**. Следовательно, по агрегатному тренду исчезновение tab breakage не подтверждено и не опровергнуто; именно относящиеся к нему события старых версий нельзя выделить без attribution. + +## 5. After-stuck recovery mitigation: работает ли? + +**Функциональный сигнал есть.** [M4](https://github.com/duckduckgo/apple-browsers/commit/41656f8d17) входит в macOS 1.210 / iOS 7.240 и при подтверждённом hang пытается reload embedded extension (remote flag по умолчанию enabled). `recovered.after.extension.reload.daily` отправляется только после реального успешного CPM-ответа текущего поколения extension. В релизный день таких событий от `messaging_stuck` — **916 iOS / 354 macOS**. Все `recovered.after` вместе дают 963/1 440 = **66,9%** от числа stuck daily на iOS и 362/489 = **74,0%** на macOS, тогда как в предшествующих пятидневных окнах число пикселей этого имени относительно stuck daily составляло **3,23%** (iOS 7.239) и **2,70%** (macOS 1.209). Это большой скачок, согласующийся с автоматическим reload. Эти отношения **не success rate**: имена пикселей независимо throttled, эпизоды не соединены, одни установки могли дать несколько разных сигналов. + +**Ограничение эффекта:** первый post-reload CPM probe всё ещё завершился timeout 670 раз на iOS и 234 на macOS, поэтому reload не гарантирует немедленного восстановления. Это не сбой самого API reload. Отдельный `debug.web.extension.reload.failed.daily` содержит один macOS error для `embedded / cpm_messaging_hung / load` и 223 iOS errors для **другого** `adBlocking / scriptlet_update / unload` extension. На текущих данных M4 действительно возвращает ответы после stuck у части установок; нельзя вычислить долю всех stuck-эпизодов, которые остались невосстановленными, или изменение общей частоты init failures. + +## Источники и воспроизведение сверки + +Локальная выгрузка и код подсчёта: `cpm-public-attribution-2026-10-06/` в `/Users/admin/DuckDuckGo/apple-browsers.git`. `inventory.tsv` — полный CPM daily/count перечень и actual reload errors; `initialization_daily.tsv` и `events_daily.tsv` — PII-free строки attribution; `daily_groups_exclusive.tsv`, `daily_families.tsv`, `daily_reasons.tsv`, `daily_signatures.tsv` — сводки; `release_cpm_daily_trends.tsv` — 982 строки дневных трендов шести версий. `analyze_daily.py` воспроизводит эксклюзивные группы. Код поведения: `CPMMessagingHealthMonitor.swift` (`reportFailure`, `reportSuccess`), `WebExtensionManager.swift` (`onConfirmedHang`, `reloadEmbeddedExtensionAfterCPMMessagingHang`), `WebExtensionLifecycleCoordinator.swift` (navigation gate), `PixelKit.swift` (лимит `.daily` по имени и UTC). Снимок законченного дня; для вывода о динамике incidence нужен следующий полный UTC-день новой версии и знаменатель активных установок той же версии.