12 KiB
Executable File
title, date, tags, updated
| title | date | tags | updated | |||
|---|---|---|---|---|---|---|
| CPM PR0 — complete telemetry change | 2026-10-16 |
|
2026-10-20 |
CPM PR0: one terminal report per failure episode
Verified 20 October 2026: #7376, head 5d1cb4abd2, targets release/ios/7.243.0. The implementation is pushed; the PR is closed without merge, with APPROVED review and green exact-head CI. This describes that branch, not shipped behavior. macOS #7484 still has the earlier was_stuck contract, no two-phase history, and a release-base conflict.
Implemented change:
Replace separate init_failed, stuck, recovery[with/without reload] and CPM post-reload-failure events with web_extension_cpm_episode. Each report contains the initial failure and its observed outcome, so diagnosis no longer requires joining separate failure, stuck and recovery events.
When it fires:
The first 4s timeout opens an episode and captures one diagnostic snapshot.
The pixel is submitted when the episode is closed (a qualifying dashboard response or a 5-minute deadline closes).
Further failures or extension reloads are recorded in the same episode and included in its final report. If no qualifying response arrives, the report is sent 5min after the first failure, even if the user does not open or reload another page (with outcome=no_response_before_deadline). The existing rules for confirming a persistent failure and automatically reloading the extension stay the same.
A dashboard response tells us the extension answered the app. It does not confirm that the page received its initialization reply (initResp). For example, tab B may answer while the original failing tab A is still broken.
Deadline expiry does not prove permanent failure; unfinished episodes can be lost if the monitor or process is destroyed.
Reporting frequency:
Both platforms use daily+count (.dailyAndCount). The first completed episode each day sends _daily and _count with the same summary; every later completed episode sends _count only. Daily deduplication is by event name, across all outcomes. _daily estimates installations with a completed failure episode that day; _count counts completed episodes. These are not distinct people or all affected installations: unfinished episodes can be lost. Old separately deduplicated failure/stuck/recovery totals need a new baseline before comparison.
Attribution:
Five added summary parameters:
-
reason: the first timeout's context —session_restoration,tab_crash,extension_reloadorother. Previously encoded in failure pixel names. -
stuck:false-one,true-one,false-manyortrue-many. This replaces the booleanwas_stuckadded in the earlier version of this PR. The true/false part says whether a later eligible non-restoration navigation, begun after the first failure, also timed out. The one/many part says whether timeouts were observed in one or multiple distinct tabs during the episode, including concurrent and restoration timeouts. Repeated timeouts in the same tab still count as one. One does not prove other tabs healthy; many does not prove all tabs failed. Tab identifiers stay local. -
outcome:failed_measurement_responsefor the measurement that timed out;failed_tab_responsefor a later measurement on a failing tab;other_tab_responsefor another tab;unattributed_responsefor an ambiguous current-document match; orno_response_before_deadline. -
reload_state:none(no reload observed),pending(replacement started),failed(replacement failed),loaded(replacement loaded), orresponse_timed_out(its first eligible messaging measurement timed out). Loaded alone does not prove messaging recovery. -
response_after: elapsed time since the first failure, bucketed asunder_30s,30s_to_1mor1m_to_deadline. Omitted for the no-response outcome.
Four added background-load parameters:
Ported and adapted from alex/cpm-messaging-readiness-telemetry:
-
bg_ready_after— background-load evidence at the first failure. Values:none(no current view and no attributed error 6 for the latest attempt),pending,failed, or completion-time bucketsunder_1s,1s_to_4s,4s_to_10s,10s_to_30s,over_30s. An attributed error 6 keeps the valuefailedafter its view disappears; a replacement view/context resets that attribution. -
bg_view_age— age of the current background view:under_4s,4s_to_8s,8s_to_30s,30s_to_2m,over_2m. Distinguishes a fresh wake from a failure long after view creation; omitted when no current view exists. -
bg_load_error_after— time from the affected view's creation to WebKit error 6:under_5s,5s_to_25s,25s_to_35s,over_35s. Tests whether the failure coincides with the 30-second background-load timer. -
bg_load_error_app_state— app state when that error occurred:active,inactiveorbackground(macOS: active/inactive). Helps distinguish foreground failures from background suspension conditions.
These values are captured in the first-failure snapshot and sent in the same terminal episode report, retaining daily+count. Unavailable values are omitted. The two error fields describe only the first newly observed error 6 for the corresponding background-load attempt. Repeated error-list notifications preserve its original time and app state; a replacement view/context clears that attribution. Errors seen before any view was created do not qualify.
Readiness observation shares the existing cpmBackgroundDelegateProxy switch. It calls the public loadBackgroundContent API on the next main-queue turn after a new view is created. Disabling observation invalidates pending callbacks; reenabling on an existing view leaves readiness unknown until the next view creation. Error 6 also marks the observed load failed if WebKit never completes its load callback. Later readiness changes and errors do not replace the episode's first-failure snapshot. pending means the load was still pending at that snapshot; it may complete or fail later. For example, a snapshot taken 4 seconds after view creation stays pending even if error 6 arrives at 30 seconds; that later error does not update the load fields. If observed before stuck confirmation, it appears in the bg_events continuation.
The added fields' combined distinguishability with the retained bg_events still needs checking. Daily deduplication and the absence of identifiers do not guarantee that rare payloads cannot be correlated. The triage summary quoted in the discussion used was_stuck; the current four-value stuck and two-phase history must be reflected in the reviewed contract. This documentation update does not establish privacy approval for those later changes.
app_state and open_tabs remain deferred to targeted startup/no-view diagnostics; loading_tabs is not planned for this change. These additions do not change the four-second detector or add page-side initResp acknowledgement.
Eight existing diagnostic booleans from ✓ TD: CPM failure pixels attribution: all are captured at the first failure; unavailable facts are omitted.
-
context_loaded— extension context loaded;bg_view_alive— current background view exists. -
bg_process_alive— its process is alive;bg_process_responsive— WebKit considers it responsive. -
tab_in_context— failing tab registered in WebKit;handler_registered— autoconsent native handler registered. -
tab_controller_match— tab and context controllers match;tab_has_ext_scripts— extension scripts remain registered.
bg_events contains the first-failure history and, for confirmed stuck episodes, a ; followed by events observed afterwards up to that confirmation, before its automatic recovery. Non-stuck episodes keep only the first-failure history. A standalone ... at the start of either phase means older events were dropped. Both phases share a limit of 12 events and 255 characters, including separators and markers. Oldest initial entries are dropped before continuation entries, so a long continuation can remove the entire initial history. No budget is reserved for either phase; reserving one was discussed but is not implemented. Sanitized token@age entries retain order and new repeated events. The initial snapshot is not replayed into the continuation. There is no general deduplication; only consecutive identical load-error notifications within one second are suppressed. Ages use 30s, 1m, 2m, 5m, 15m and over_15, relative to the first failure before ; and stuck confirmation after it. An empty phase has no events. Consumers split on both , and ;, ignoring empty entries and standalone .... Example: ...,load@1m,view@30s;error_e:6@30s. No second full diagnostic snapshot is collected.
Standard metadata remains: appVersion on both platforms, plus pixelSource and channel on macOS.
Remove retired pixels from ✓ TD: CPM failure pixels attribution:
-
debug_web_extension_cpm_initialization_failed_after_session_restoration -
debug_web_extension_cpm_initialization_failed_after_other -
debug_web_extension_cpm_initialization_failed_after_tab_crash -
debug_web_extension_cpm_initialization_failed_after_extension_reload -
debug_web_extension_cpm_messaging_stuck_session_restoration -
debug_web_extension_cpm_messaging_stuck_tab_crash -
debug_web_extension_cpm_messaging_stuck_extension_reload -
debug_web_extension_cpm_messaging_stuck_other -
debug_web_extension_cpm_messaging_recovered_without_extension_reload -
debug_web_extension_cpm_messaging_recovered_after_extension_reload -
debug_web_extension_cpm_messaging_extension_reload_failed
Parameters removed from transmission:
context_errors, network_restarted, critical_memory_age, bg_view_creations, bg_view_leaked_count, app_version_change, app_launch_age, background_graveyard_enabled and recovery_from. Episode state and response attribution replace recovery_from. Graveyard attribution is also removed from the diagnostic model and monitor, including the unused attribution state and methods. The graveyard mitigation itself is unchanged. The retired parameter encoder is removed so only the episode report builds the transmitted payload. App tests added for the dropped open/loading-tab measurements are removed with their project entries.
What this still cannot diagnose:
A late same-measurement dashboard response without reload helps identify a transient timeout. stuck=false-* only means persistence was not confirmed; true-* still cannot exclude a working page whose dashboard confirmation was lost. There is no page-side initResp ACK or last-confirmed-stage field. One/many measures observed failing tabs, without testing every tab or grouping failures by window.
The final outcome of an initially pending load is not reported explicitly. Pre-stuck errors can reach the continuation, but successful completion does not update the frozen load fields. Network-replacement attribution relative to the current background view is also missing. The separate web_extension_cpm_network_process_recovery_applied in #7459 uses daily+count with no custom parameters; it counts a restart being applied, not all crashes or successful recovery. These follow-up measurements are not part of #7376. Detailed gaps and production truncation evidence: cpm-status-2026-10-15#6. Телеметрия.
Validation and lifetime:
On 5d1cb4abd2: 777 WebExtensions tests passed, zero failures; strict SwiftLint passed for all six changed Swift files; both platforms' pixel definitions passed validation. Tests used an isolated package copy with refreshed dependency resolution; the worktree's user-edited lockfile was preserved. All four required CI result checks and Danger are green on this head. The episode pixel is temporary; both definitions list expires: 2027-01-15, which does not itself remove runtime code.