MetricKit API Reference
Complete API reference for collecting field performance metrics and diagnostics using MetricKit.
Overview
MetricKit provides aggregated, on-device performance and diagnostic data from users who opt into sharing analytics. Data is delivered daily (or on-demand in development).
When to Use This Reference
Use this reference when:
- Setting up MetricKit subscriber in your app
- Parsing MXMetricPayload or MXDiagnosticPayload
- Symbolicating MXCallStackTree crash data
- Understanding background exit reasons (jetsam, watchdog)
- Integrating MetricKit with existing crash reporters
For hang diagnosis workflows, see axiom-hang-diagnostics.
For general profiling with Instruments, see axiom-performance-profiling.
For memory debugging including jetsam, see axiom-memory-debugging.
Common Gotchas
- 24-hour delay β MetricKit data arrives once daily; it's not real-time debugging
- Call stacks require symbolication β MXCallStackTree frames are unsymbolicated; keep dSYMs
- Opt-in only β Only users who enable "Share with App Developers" contribute data
- Aggregated, not individual β You get counts and averages, not per-user traces
- Simulator doesn't work β MetricKit only collects on physical devices
iOS Version Support:
| Feature |
iOS Version |
| Basic metrics (battery, CPU, memory) |
iOS 13+ |
| Diagnostic payloads |
iOS 14+ |
| Hang diagnostics |
iOS 14+ |
| Launch diagnostics |
iOS 16+ |
| Immediate delivery in dev |
iOS 15+ |
Part 1: Setup
Basic Integration
import MetricKit
class AppMetricsSubscriber: NSObject, MXMetricManagerSubscriber {
override init() {
super.init()
MXMetricManager.shared.add(self)
}
deinit {
MXMetricManager.shared.remove(self)
}
func didReceive(_ payloads: [MXMetricPayload]) {
for payload in payloads {
processMetrics(payload)
}
}
func didReceive(_ payloads: [MXDiagnosticPayload]) {
for payload in payloads {
processDiagnostics(payload)
}
}
}
Registration Timing
Register subscriber early in app lifecycle:
@main
struct MyApp: App {
@StateObject private var metricsSubscriber = AppMetricsSubscriber()
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Or in AppDelegate:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
metricsSubscriber = AppMetricsSubscriber()
return true
}
Development Testing
In iOS 15+, trigger immediate delivery via Debug menu:
Xcode > Debug > Simulate MetricKit Payloads
Or programmatically (debug builds only):
#if DEBUG
#endif
Part 2: MXMetricPayload
MXMetricPayload contains aggregated performance metrics from the past 24 hours.
Payload Structure
func processMetrics(_ payload: MXMetricPayload) {
let start = payload.timeStampBegin
let end = payload.timeStampEnd
let version = payload.metaData?.applicationBuildVersion
if let cpuMetrics = payload.cpuMetrics {
processCPU(cpuMetrics)
}
if let memoryMetrics = payload.memoryMetrics {
processMemory(memoryMetrics)
}
if let launchMetrics = payload.applicationLaunchMetrics {
processLaunches(launchMetrics)
}
}
CPU Metrics (MXCPUMetric)
func processCPU(_ metrics: MXCPUMetric) {
let cpuTime = metrics.cumulativeCPUTime
if #available(iOS 14.0, *) {
let instructions = metrics.cumulativeCPUInstructions
}
}
Memory Metrics (MXMemoryMetric)
func processMemory(_ metrics: MXMemoryMetric) {
let peakMemory = metrics.peakMemoryUsage
let avgSuspended = metrics.averageSuspendedMemory
}
Launch Metrics (MXAppLaunchMetric)
func processLaunches(_ metrics: MXAppLaunchMetric) {
let firstDrawHistogram = metrics.histogrammedTimeToFirstDraw
let resumeHistogram = metrics.histogrammedApplicationResumeTime
if #available(iOS 15.2, *) {
let optimizedLaunch = metrics.histogrammedOptimizedTimeToFirstDraw
}
for bucket in firstDrawHistogram.bucketEnumerator {
if let bucket = bucket as? MXHistogramBucket<UnitDuration> {
let start = bucket.bucketStart
let end = bucket.bucketEnd
let count = bucket.bucketCount
}
}
}
Application Exit Metrics (MXAppExitMetric) β iOS 14+
@available(iOS 14.0, *)
func processExits(_ metrics: MXAppExitMetric) {
let fg = metrics.foregroundExitData
let bg = metrics.backgroundExitData
let fgNormal = fg.cumulativeNormalAppExitCount
let fgWatchdog = fg.cumulativeAppWatchdogExitCount
let fgMemoryLimit = fg.cumulativeMemoryResourceLimitExitCount
let fgMemoryPressure = fg.cumulativeMemoryPressureExitCount
let fgBadAccess = fg.cumulativeBadAccessExitCount
let fgIllegalInstruction = fg.cumulativeIllegalInstructionExitCount
let fgAbnormal = fg.cumulativeAbnormalExitCount
let bgSuspended = bg.cumulativeSuspendedWithLockedFileExitCount
let bgTaskTimeout = bg.