7.7 KiB
TD: Pixel Definition: CPM M3 Telemetry (macOS/iOS)
Author: Alex M
Reviewer: TBD
Stakeholders: Michal, Konrad, Russell (from the first CPM Tech Design; confirm for M3)
Project: CPM: root-cause the stuck embedded extension messaging (macOS/iOS)
Previous Tech Design: CPM breakage pixels
Background & Requirements
The first CPM pixels detect initialization failure, a stuck messaging episode and recovery. They do not explain whether a failure coincides with background-process termination, a context-load error or incorrect tab wiring.
Forced background-process termination can reproduce a persistent CPM outage. M3 adds native-side diagnostics to investigate whether the same failure occurs in production on iOS and macOS, without relying on the extension's messaging channel.
Problem Statement
Distinguish background-process/context failures from tab-local problems and identify failed extension reload operations. Collect the diagnostic state alongside existing failures, without page content, URLs or persistent identifiers.
M3 provides evidence for the production-validation milestone; it does not implement graveyard mitigation or an A/B experiment.
Recommended Approach
Keep the existing CPM failure/stuck detection. A shared in-memory recorder collects lifecycle events, critical-memory-pressure notifications and current WebKit/tab state. When a failure or stuck pixel fires, attach a best-effort snapshot. No additional JavaScript probes or periodic telemetry uploads are introduced.
A forwarding delegate proxy observes background-process termination and responsiveness callbacks. The original delegate owns the proxy; the proxy references it weakly. A remote flag enables/disables proxy installation, not the entire diagnostics recorder.
| Pixel | Trigger | Frequency |
|---|---|---|
debug_web_extension_cpm_initialization_failed_after_<reason> |
Existing initialization failure; add diagnostic parameters. | Daily |
debug_web_extension_cpm_messaging_stuck_<reason> |
Existing failure confirmed by a later eligible navigation; add diagnostic parameters. | Daily + count, once per episode |
debug_web_extension_reload_failed |
New: extension unload/load fails during a reload operation. Applies to all supported extension types. | Daily + count |
<reason>: session_restoration, tab_crash, extension_reload, other. PixelKit applies standard frequency/platform suffixes. Standard metadata includes appVersion; macOS also declares pixelSource and channel.
Recovery pixels remain unchanged. The new reload-failure pixel reports a failed reload operation, unlike the existing cpm_messaging_extension_reload_failed, which reports CPM failure after a successful reload.
Failure / stuck parameters
Unavailable optional facts are omitted. Boolean values are true / false.
| Parameter | What is collected |
|---|---|
extension_context_loaded |
Context is loaded — boolean. |
background_view_alive |
Current background WKWebView exists — boolean. |
background_web_process_alive |
Background process identifier is nonzero — boolean; PID is not sent. |
background_web_process_responsive |
WebKit's process-responsiveness verdict — boolean. |
network_process_restarted |
Network PID differs from the value at context load — boolean; PIDs are not sent. |
tab_known_to_webkit |
Failing tab is in WebKit's open-tabs set — boolean. |
tab_controller_matches_context |
Tab and context use the same extension controller — boolean. |
tab_has_extension_user_scripts |
Registered scripts include the expected extension world — boolean, not proof of execution. |
native_handler_registered |
Autoconsent native-message handler is registered — boolean, not proof of message delivery. |
memory_pressure_critical |
Age of last observed critical pressure: none, under_1_min, under_5_min, under_30_min, over_30_min. |
background_view_create_count |
Creations since context load: 0, 1, 2, 3_to_5, over_5. |
background_view_leaked_count |
Retained views beyond the expected current view; same buckets. Not proof of a leak. |
extension_context_errors |
none or accumulated error descriptors: mapped context-error names, with raw domain/code for other or underlying errors. No localized text; no explicit payload cap. |
background_events |
Recent lifecycle sequence with relative ages in whole seconds. |
The recorder keeps 40 events in memory; the pixel includes at most the last 12 and 255 characters, dropping oldest entries first. Format: event_name@-seconds, relative to snapshot time.
Events: load, view, dealloc, unresponsive, responsive, proxy_on, proxy_off, died_<reason>, error_<descriptor>. Termination reasons: memory_limit, cpu_limit, requested_by_client, crash, shared_crash_limit, unknown. Error events represent background-load failures. Event labels are lowercased, character-filtered and capped at 64 characters.
Example: view@-60,died_crash@-42,error_background_failed_to_load@-41.
Reload-failure parameters
| Parameter | Values |
|---|---|
extension_type |
embedded, darkMode, adBlocking, searchToken, unknown |
reload_trigger |
data_clearing, scriptlet_update, explicit |
reload_phase |
unload, load, lightweight_load, full_load, fallback_load |
reload_error |
already_loaded, not_loaded, base_url_in_use, no_background_content, background_failed_to_load, unknown, other |
These are allowlisted enums; this pixel does not send raw error domains, codes or messages.
Testing
- Unit tests: parameter serialization, buckets, timeline limits, attachment to failure/stuck pixels, reload-error mapping, delegate forwarding, ownership and runtime flag changes.
- Integration validation on iOS/macOS: force background-process termination, check the emitted diagnostics, test proxy on/off and extension reload failures. Confirm unknown SPI values are omitted.
- Privacy validation: inspect actual payloads and run both platform schema validators. Confirm URLs, identifiers and error messages are absent. Review exact-second timelines and error-domain/code values before release.
Additional Considerations (if applicable)
Privacy
New pixel and additional parameters require Privacy Triage. No intentional collection of browsing URLs, search queries, page content, message payloads, tab/context IDs or PIDs in these payloads. Exact-second timelines and unrestricted error-domain/code combinations can be high-cardinality; bucketing/allowlisting needs a decision. data_clearing discloses the operation preceding a failed reload.
Current local diagnostics logs separately include raw errors with privacy: .public; remove/redact these before production. Pixel approval does not approve those logs.
Security
Uses guarded private WebKit selectors for process/script facts. Validate supported OS versions; missing facts must not block pixel delivery.
Site Breakage
No intended page-behavior changes. However, the investigation recorded a changed reproduction with the delegate proxy installed; validate the current proxy on/off before treating observations as an unaffected baseline.
Experimentation
None in M3. Graveyard mitigation and A/B testing remain separate milestones.
Operational
Update the existing CPM Grafana board for the new fields and reload failures. Agree a diagnostic removal/review date; none is enforced currently. Failure-only snapshots do not provide a denominator of all process deaths or prove an all-tabs outage. Rolling timelines can lose the trigger; deferred snapshots can observe newer state.
Localization / Internationalization
None.