What does MetricKit give you in production, how do you subscribe, and what is the difference between metric and diagnostic payloads?
Predict first
A fresh app registers a MetricKit subscriber. How many past payloads does it have, and does registering work?
import MetricKit
final class Collector: NSObject, MXMetricManagerSubscriber {
func didReceive(_ payloads: [MXMetricPayload]) {}
func didReceive(_ payloads: [MXDiagnosticPayload]) {}
}
let manager = MXMetricManager.shared
let collector = Collector()
manager.add(collector)
print(manager.pastPayloads.count, manager.pastDiagnosticPayloads.count)
manager.remove(collector)
- 0 0, and it works
- It crashes because there is no payload
- 1 1, a sample payload is created
Mental model. The lab is a test track; MetricKit is the fleet’s dashboard cameras. They show what the cars do on real roads, but you get the footage the next day, not live.
MetricKit collects on-device metrics from real users and delivers them to your app. You adopt MXMetricManagerSubscriber, register with MXMetricManager.shared.add(_:) as early as possible (at launch), and implement didReceive(_:) for two payload kinds. MXMetricPayload aggregates the last period (about 24 hours): launch-time and hang-time histograms, memory and CPU use, disk writes, cellular and Wi-Fi bytes, display, location and animation (scroll hitch) metrics, plus any custom mxSignpost intervals you defined. MXDiagnosticPayload carries individual events with call-stack trees: hangs (MXHangDiagnostic), CPU and disk-write exceptions, app-launch diagnostics and crashes. You forward the data to your own backend, tagged with app version and device model, and chart percentiles across releases. Payloads are delivered after the fact, not when the event happens, and a subscriber has to be registered for them to arrive.
It complements rather than replaces other tools. A crash reporter shows crashes quickly with rich context; MetricKit shows non-crash problems (slow launches, hangs, hitches, energy, disk writes) and the same data feeds the Xcode Organizer, which charts launch, hang rate, memory, disk writes, battery and scrolling by version without any code, for users who opted in to share analytics. Do not expect a payload on demand: on a development machine use Xcode’s Debug › Simulate MetricKit Payloads to test your handler, and note that the simulator and a fresh install have no past payloads. Treat the payloads as personal-adjacent telemetry: send only what you need and respect the app’s privacy disclosures.
Registration is ordinary API; payloads only exist after the system has collected a period of real use, so a fresh install has none.
Common traps
- Registering the subscriber late. Register at launch, or payloads delivered at that moment are missed until the next pass.
- Expecting real-time data. Payloads arrive after the period ends; for immediate signals use logging or a crash reporter.
They might follow up with
- Metric versus diagnostic payload? Metrics are aggregates over a period; diagnostics are individual events with stack traces.
- Where do you see it without code? Xcode Organizer, for versions with enough opted-in users.
Related questions
- 21.3.2 How do you build a performance culture on a team: budgets, regression gates, ownership and release guardrails?
- 21.1.2 How do you measure performance reliably: what makes numbers lie, and why do percentiles beat averages?
- 21.2.2 How do signposts and Points of Interest work, and how do you turn a measurement into an XCTest performance…
- 6.4.3 Your app launches slowly. How do you find out why and what do you cut?
How do you build a performance culture on a team: budgets, regression… →