Diagnostics Persistence is a service that stores specific Inspect data on device across one or more reboots. If you need to track failure states, historical metrics, or other telemetry that must survive a restart, configure this service to save your data automatically.
Persistence is particularly useful for recovering diagnostic data after:
To configure Persistence to save your component's Inspect data, follow these steps:
Select the specific data you need to save. You will need the exact INSPECT: selector for your component's data (e.g., INSPECT:core/pkg-resolver:root/resolver_service/active_package_resolves:*).
Create a new .persist file in either //src/diagnostics/config/persistence or //vendor/*/diagnostics/config/persistence.
The file uses JSON5. Define the parameters for the data you wish to persist:
[ { tag: "cache-fallbacks", // Unique name service_name: "pkg-resolver", // Grouping for tags max_bytes: 500, // Max size of the persisted data min_seconds_between_fetch: 3600, // How frequently to sample the data selectors: [ "INSPECT:core/pkg-resolver:root/resolver_service:cache_fallbacks_due_to_not_found", "INSPECT:core/pkg-resolver:root/resolver_service/active_package_resolves:*", ], }, ]
max_bytes {#estimate-max_bytes}The size of the persisted data is enforced at runtime. If your selectors fetch more data than max_bytes, all of the saved data for this tag will be permanently dropped and replaced with a single error string instead.
To estimate the correct max_bytes limit:
ffx inspect show locally with your exact selectors, and pipe the output through jq to strip away un-persisted data. Finally, count the bytes using wc -c. For example:ffx --machine json inspect show \ 'core/pkg-resolver:root/resolver_service:cache_fallbacks_due_to_not_found' \ 'core/pkg-resolver:root/resolver_service/active_package_resolves:*' \ | jq -c '.[] | pick(.moniker, .payload.root)' \ | wc -c
Add your new configuration file to the build by adding it to the diagnostics-persistence package configuration in //bundles/assembly/BUILD.gn.
Find the package_name = "diagnostics-persistence" block and add your .persist file to the files list:
package_name = "diagnostics-persistence" files = [ { source = "//src/diagnostics/config/persistence/netstack.persist" destination = "netstack.persist" }, + { + source = "//src/sys/pkg/bin/pkg-resolver/pkg-resolver.persist" + destination = "pkg-resolver.persist" + }, ]
On the next boot (after the software update check completes), the saved data is re-published into Inspect.
The data is hosted by the diagnostics-persistence component. The original path is prefixed with your configured service_name and tag.
$ ffx inspect show core/diagnostics/persistence core/diagnostics/persistence: root: persist: pkg-resolver: cache-fallbacks: core/pkg-resolver: resolver_service: cache_fallbacks_due_to_not_found: 2
The .persist JSON5 file format expects an array of objects, where each object defines a Persistence Tag. Each tag accepts the following fields:
| Field | Type | Description |
|---|---|---|
tag | string | The unique identifier for this data collection within the service_name. Must be lowercase and hyphens only (e.g., "my-feature-stats"). |
service_name | string | A grouping identifier for related tags. Must be lowercase and hyphens only (e.g., "my-service"). |
selectors | []string | A list of exact INSPECT: selectors to harvest and save. |
max_bytes | integer | The maximum allowed size of the fetched Inspect payload in bytes. If the sampled data exceeds this limit, the saved data will be replaced with an error string. |
min_seconds_between_fetch | integer | How frequently Archivist should sample these selectors. |
persist_across_boot | boolean (default false) | If true, saved data is not cleared on the next boot and will continue to accumulate historical boot data. |
Persistence is a powerful tool for debugging, but it can also be a privacy risk if not used carefully.
Cross-boot linkage: Enabling persist_across_boot preserves saved data across boots, accumulating historical data. This creates a long-term record of device usage, which could be used to track users across multiple boots. This can also violate other privacy safeguards, such as fingerprinting a device or user across a time-limited pseudonymous ID.
Data retention: Persistence data is stored on the device and can be accessed by anyone with physical access to the device. It is important to consider the sensitivity of the data you are persisting and whether it should be protected with additional security measures.
Data minimization: Only persist the data that you need to debug your component. Avoid persisting unnecessary data, as this can increase the privacy risk.
Yes. Persistence provides built-in support for Inspect Lazy Nodes. Persistence registers its required selectors and fetch frequencies with the Archivist. At each interval, the Archivist actively queries the component's selectors, which triggers the evaluation of any Lazy Nodes, allowing the system to save their dynamically generated data.