From fc0481ac42233019288cbd5c57c1d855f37465a3 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Thu, 12 Nov 2026 15:55:08 +0600 Subject: [PATCH] [2026-11-12] eagle: work/projects/cpm-permanent-breakage-metric-tech-design-2026-11-10.md --- ...-breakage-metric-tech-design-2026-11-10.md | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/work/projects/cpm-permanent-breakage-metric-tech-design-2026-11-10.md b/work/projects/cpm-permanent-breakage-metric-tech-design-2026-11-10.md index ae487f1f..a0c838be 100644 --- a/work/projects/cpm-permanent-breakage-metric-tech-design-2026-11-10.md +++ b/work/projects/cpm-permanent-breakage-metric-tech-design-2026-11-10.md @@ -27,18 +27,29 @@ Rework the health monitor so that it finds the tabs whose pages never get a mess ## Recommended Approach -1. **Detection.** While a page initializes, the extension sends the app a message from that tab. When a page loads that should get such a message, the app waits 30 seconds. The page counts if it is http(s), the extension is loaded, and it is not the browser's error page, a back/forward navigation or a restored session. If no message arrives, the tab is **silent**. A message that arrives later still counts as an answer; a message saying that the extension cannot answer (no configuration or settings) does not. Time the app spends suspended is not counted. There is no timer: the app checks for expired waits whenever another event comes in (a page loads, a tab closes, a message arrives, the app goes to the background). -2. **Matching problem.** A message carries the extension's tab id and the page URL. The app cannot see the tab id, so it can only match the message to a tab by the URL (host and path). Two tabs on the same page cannot be told apart: the message counts as an answer for both, and a silent tab hides behind a working one. -3. **Solution.** The extension adds to each message the tab's index in its window, the id of that window and the ids of all windows, as the browser reports them. The app numbers its windows in the order it hands them to WebKit, and WebKit gives each window its id from a growing counter in that same order. So the k-th smallest of the window ids is the k-th window of the app, and the tab is the one at the index in that window. The app remembers which tab the extension's tab id belongs to until the tab closes or the extension reloads. If the app cannot tell the window (an older extension, or the app and the extension count different numbers of windows), it matches by the URL as before. -4. Two pixels: +1. **When a tab is counted as silent.** While a page initializes, the extension sends the app a message from that tab. When a page loads in a tab, the app waits 30 seconds for that message, provided that: + - the address is http or https; + - the navigation is a normal one: not the browser's error page, not a back/forward navigation, not a restored session (the extension may not run there); + - the extension is loaded. + + If no message about the page arrives within 30 seconds, the tab is **silent** and one `web_extension_cpm_breakage` pixel is sent for it. +2. **When a tab is not counted.** + - A message that arrives late but before the app checks still counts as an answer, as does a message sent up to 2 seconds before the page loaded. + - A message saying that the extension cannot answer (no configuration or settings) is not an answer. + - The wait is dropped when the tab closes, when its page process crashes, when the tab moves on to a page that does not qualify, and when the extension reloads. A new qualifying page in the same tab starts a new wait. + - Time the app spends suspended (iOS in the background, macOS asleep) is not counted. + - There is no timer: the app checks for expired waits whenever another event comes in (a page loads, a tab closes, a message arrives, the app goes to the background). +3. **Matching problem.** A message carries the extension's tab id and the page URL. The app cannot see the tab id, so it can only match the message to a tab by the URL (host and path). Two tabs on the same page cannot be told apart: the message counts as an answer for both, and a silent tab hides behind a working one. +4. **Solution.** The extension adds to each message the tab's index in its window, the id of that window and the ids of all windows, as the browser reports them. The app numbers its windows in the order it hands them to WebKit, and WebKit gives each window its id from a growing counter in that same order. So the k-th smallest of the window ids is the k-th window of the app, and the tab is the one at the index in that window. The app remembers which tab the extension's tab id belongs to until the tab closes or the extension reloads. If the app cannot tell the window (an older extension, or the app and the extension count different numbers of windows), it matches by the URL as before. +5. Two pixels: | Pixel | When it is sent | Frequency | | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | | `web_extension_cpm_breakage` | A tab becomes silent. Parameter `tabs`: `one` if no other tab was silent since the extension last sent a message (the page is the likely cause), `many` if another one was (the extension is the likely cause). | Daily + count | | `web_extension_cpm_breakage_persistent` | A second tab becomes silent and the extension sent no message in between. Once per such series. | Daily + count | -5. Remove `web_extension_cpm_episode`, `web_extension_cpm_background_load_restart` and `web_extension_cpm_network_process_recovery_applied`, together with the code that only fed them. The new pixels must ship in the same release, otherwise there is no CPM breakage pixel at all. -6. The success metric is the number of installs per day with the persistent pixel, divided by DAU. +6. Remove `web_extension_cpm_episode`, `web_extension_cpm_background_load_restart` and `web_extension_cpm_network_process_recovery_applied`, together with the code that only fed them. The new pixels must ship in the same release, otherwise there is no CPM breakage pixel at all. +7. The success metric is the number of installs per day with the persistent pixel, divided by DAU. ## Testing