Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
dpearson2699 avatar

Metrickit

  • 2.1k installs
  • 944 repo stars
  • Updated July 15, 2026
  • dpearson2699/swift-ios-skills

metrickit is an agent skill that Collect and analyze on-device performance metrics and crash diagnostics using MetricKit. Use when setting up MXMetricManager, handling MXMetricPayload or MXDiag.

About

Collect and analyze on-device performance metrics and crash diagnostics using MetricKit Use when setting up MXMetricManager handling MXMetricPayload or MXDiagnosticPayload processing crash hang disk-write diagnostics via MXCallStackTree adding custom signpost metrics correcting mxSignpost or extended launch measurement code or uploading telemetry to an analytics backend name metrickit description Collect and analyze on-device performance metrics and crash diagnostics using MetricKit Use when setting up MXMetricManager handling MXMetricPayload or MXDiagnosticPayload processing crash hang disk-write diagnostics via MXCallStackTree adding custom signpost metrics correcting mxSignpost or extended launch measurement code or uploading telemetry to an analytics backend MetricKit Collect aggregated performance metrics and crash diagnostics from production devices using MetricKit The framework delivers daily metric payloads CPU memory launch time hang rate animation hitches network usage and diagnostic payloads crashes hangs disk-write exceptions with call-stack trees for triage Contents Subscriber Setup subscriber-setup Receiving Metric Payloads receiving-metric-payloads Receiving Diagnos.

  • [Subscriber Setup](#subscriber-setup)
  • [Receiving Metric Payloads](#receiving-metric-payloads)
  • [Receiving Diagnostic Payloads](#receiving-diagnostic-payloads)
  • [Key Metrics](#key-metrics)
  • [Call Stack Trees](#call-stack-trees)

Metrickit by the numbers

  • 2,116 all-time installs (skills.sh)
  • +114 installs in the week ending Jul 29, 2026 (Skillselion tracking)
  • Ranked #366 of 2,159 Testing & QA skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Jul 31, 2026 (Skillselion catalog sync)
At a glance

metrickit capabilities & compatibility

Capabilities
[subscriber setup](#subscriber setup) · [receiving metric payloads](#receiving metric pa · [receiving diagnostic payloads](#receiving diagn · [key metrics](#key metrics) · [call stack trees](#call stack trees)
Use cases
documentation
From the docs

What metrickit says it does

--- name: metrickit description: "Collect and analyze on-device performance metrics and crash diagnostics using MetricKit.
SKILL.md
MetricKit starts accumulating reports after the first access to `MXMetricManager.shared`.
SKILL.md
When backfilling, state precisely that `pastPayloads` and `pastDiagnosticPayloads` return reports generated since the last allocation of the shared manager instance.
SKILL.md
The array may contain multiple payloads if prior deliveries were missed.
SKILL.md
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill metrickit

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs2.1k
repo stars944
Security audit3 / 3 scanners passed
Last updatedJuly 15, 2026
Repositorydpearson2699/swift-ios-skills

What problem does metrickit solve for developers using this skill?

Collect and analyze on-device performance metrics and crash diagnostics using MetricKit. Use when setting up MXMetricManager, handling MXMetricPayload or MXDiagnosticPayload, processing crash/hang/dis

Who is it for?

Developers who need metrickit patterns described in the cached skill documentation.

Skip if: Skip when docs are empty or the task is outside the skill's documented scope.

When should I use this skill?

Collect and analyze on-device performance metrics and crash diagnostics using MetricKit. Use when setting up MXMetricManager, handling MXMetricPayload or MXDiagnosticPayload, processing crash/hang/dis

What you get

Actionable workflows and conventions from SKILL.md for metrickit.

  • MetricKit subscriber implementation
  • Payload persistence layer
  • Telemetry review notes

Files

SKILL.mdMarkdownGitHub ↗

MetricKit

Collect aggregated performance metrics and crash diagnostics from production devices using MetricKit. The framework delivers daily metric payloads (CPU, memory, launch time, hang rate, animation hitches, network usage) and diagnostic payloads (crashes, hangs, disk-write exceptions) with call-stack trees for triage.

Contents

Subscriber Setup

Register a subscriber as early as possible — ideally in application(_:didFinishLaunchingWithOptions:) or App.init. MetricKit starts accumulating reports after the first access to MXMetricManager.shared. When backfilling, state precisely that pastPayloads and pastDiagnosticPayloads return reports generated since the last allocation of the shared manager instance.

import MetricKit

final class MetricsSubscriber: NSObject, MXMetricManagerSubscriber {
    static let shared = MetricsSubscriber()

    func subscribe() {
        let manager = MXMetricManager.shared
        manager.add(self)

        // Reports generated since the last allocation of the shared manager.
        processMetricPayloads(manager.pastPayloads)
        processDiagnosticPayloads(manager.pastDiagnosticPayloads)
    }

    func unsubscribe() {
        MXMetricManager.shared.remove(self)
    }

    func didReceive(_ payloads: [MXMetricPayload]) {
        processMetricPayloads(payloads)
    }

    func didReceive(_ payloads: [MXDiagnosticPayload]) {
        processDiagnosticPayloads(payloads)
    }
}

UIKit Registration

func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    MetricsSubscriber.shared.subscribe()
    return true
}

SwiftUI Registration

@main
struct MyApp: App {
    init() {
        MetricsSubscriber.shared.subscribe()
    }
    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

Receiving Metric Payloads

MXMetricPayload arrives approximately once per 24 hours containing aggregated metrics. The array may contain multiple payloads if prior deliveries were missed.

func didReceive(_ payloads: [MXMetricPayload]) {
    for payload in payloads {
        let begin = payload.timeStampBegin
        let end = payload.timeStampEnd
        let version = payload.latestApplicationVersion

        // Persist raw JSON before processing
        let jsonData = payload.jsonRepresentation()
        persistPayload(jsonData, from: begin, to: end)

        enqueueMetricProcessing(jsonData)
    }
}

Availability: MXMetricPayload — iOS 13.0+, iPadOS 13.0+, Mac Catalyst 13.1+, macOS 10.15+, visionOS 1.0+

Receiving Diagnostic Payloads

MXDiagnosticPayload delivers crash, hang, CPU exception, disk-write, and app-launch diagnostics where supported. On iOS 15+ and macOS 12+, supported diagnostics can arrive as soon as available rather than bundled with the daily report.

func didReceive(_ payloads: [MXDiagnosticPayload]) {
    for payload in payloads {
        let jsonData = payload.jsonRepresentation()
        persistPayload(jsonData)
        enqueueDiagnosticProcessing(jsonData)
    }
}

In the background processor, inspect the typed diagnostic arrays after the raw payload is durable:

func processDiagnosticPayload(_ payload: MXDiagnosticPayload) {
    if let crashes = payload.crashDiagnostics {
        for crash in crashes {
            handleCrash(crash)
        }
    }
    if let hangs = payload.hangDiagnostics {
        for hang in hangs {
            handleHang(hang)
        }
    }
    if let diskWrites = payload.diskWriteExceptionDiagnostics {
        for diskWrite in diskWrites {
            handleDiskWrite(diskWrite)
        }
    }
    if let cpuExceptions = payload.cpuExceptionDiagnostics {
        for cpuException in cpuExceptions {
            handleCPUException(cpuException)
        }
    }
    #if os(iOS) || targetEnvironment(macCatalyst) || os(visionOS)
    if #available(iOS 16.0, macCatalyst 16.0, visionOS 1.0, *),
       let launchDiagnostics = payload.appLaunchDiagnostics {
        for launchDiagnostic in launchDiagnostics {
            handleSlowLaunch(launchDiagnostic)
        }
    }
    #endif
}

Availability: MXDiagnosticPayload — iOS 14.0+, iPadOS 14.0+, Mac Catalyst 14.0+, macOS 12.0+, visionOS 1.0+. appLaunchDiagnostics requires iOS 16.0+, iPadOS 16.0+, Mac Catalyst 16.0+, or visionOS 1.0+.

Key Metrics

Launch Time — MXAppLaunchMetric

if let launch = payload.applicationLaunchMetrics {
    let firstDraw = launch.histogrammedTimeToFirstDraw
    let optimized = launch.histogrammedOptimizedTimeToFirstDraw
    let resume = launch.histogrammedApplicationResumeTime
    let extended = launch.histogrammedExtendedLaunch
}

Run Time — MXAppRunTimeMetric

if let runTime = payload.applicationTimeMetrics {
    let fg = runTime.cumulativeForegroundTime    // Measurement<UnitDuration>
    let bg = runTime.cumulativeBackgroundTime
    let bgAudio = runTime.cumulativeBackgroundAudioTime
    let bgLocation = runTime.cumulativeBackgroundLocationTime
}

CPU, Memory, and Responsiveness

if let cpu = payload.cpuMetrics {
    let cpuTime = cpu.cumulativeCPUTime              // Measurement<UnitDuration>
}
if let memory = payload.memoryMetrics {
    let peakMemory = memory.peakMemoryUsage           // Measurement<UnitInformationStorage>
}
if let responsiveness = payload.applicationResponsivenessMetrics {
    let hangTime = responsiveness.histogrammedApplicationHangTime
}
if let animation = payload.animationMetrics {
    let scrollHitchRate = animation.scrollHitchTimeRatio  // Measurement<Unit>
}

Network and Cellular

if let network = payload.networkTransferMetrics {
    let wifiUp = network.cumulativeWifiUpload          // Measurement<UnitInformationStorage>
    let wifiDown = network.cumulativeWifiDownload
    let cellUp = network.cumulativeCellularUpload
    let cellDown = network.cumulativeCellularDownload
}

App Exit Metrics

if let exits = payload.applicationExitMetrics {
    let fg = exits.foregroundExitData
    let bg = exits.backgroundExitData
    // Inspect normal, abnormal, watchdog, memory, etc.
}

Call Stack Trees

MXCallStackTree is attached to each diagnostic. Use jsonRepresentation() to extract frame data, then symbolicate with atos or by uploading dSYMs to your analytics service.

See references/metrickit-patterns.md for crash/hang handling code and JSON structure details.

Availability: MXCallStackTree — iOS 14.0+, iPadOS 14.0+, Mac Catalyst 14.0+, macOS 12.0+, visionOS 1.0+

Custom Signpost Metrics

Use mxSignpost with a MetricKit log handle to capture custom performance intervals. Leave the advanced dso, signpostID, and format parameters at their documented defaults. Custom metrics appear in the daily MXMetricPayload under signpostMetrics; call that out when reviewing custom MetricKit instrumentation. When correcting custom signpost code, explicitly name MXMetricPayload.signpostMetrics so the caller knows where the data lands. Do not allocate or pass an OSSignpostID for the basic MetricKit pattern; use the defaulted mxSignpost(.begin/.end, log:name:) calls unless there is a specific overlapping-interval reason to do otherwise.

let metricLog = MXMetricManager.makeLogHandle(category: "Networking")
mxSignpost(.begin, log: metricLog, name: "DataFetch")
defer { mxSignpost(.end, log: metricLog, name: "DataFetch") }

let data = try await fetchData()

See references/metrickit-patterns.md for signpost emission patterns and reading custom metrics from payloads.

Exporting and Uploading Payloads

Both payload types provide jsonRepresentation() for serialization. Always persist raw JSON to disk before processing. Use pastPayloads and pastDiagnosticPayloads on launch to retrieve reports generated since the last allocation of the shared manager instance.

See references/metrickit-patterns.md for export code and past payload retrieval.

Extended Launch Measurement

Track post-first-draw setup work as part of the launch metric on iOS 16+, iPadOS 16+, Mac Catalyst 16+, macOS 13+, and visionOS 1+:

let taskID = MXLaunchTaskID("com.example.app.loadDatabase")
try MXMetricManager.extendLaunchMeasurement(forTaskID: taskID)
defer { try? MXMetricManager.finishExtendedLaunchMeasurement(forTaskID: taskID) }
restoreCachedState()

When correcting extended launch code, include the whole operational contract: availability is iOS/iPadOS/Mac Catalyst 16+, macOS 13+, and visionOS 1+; call the throwing MXMetricManager type methods on the main thread; start the first task before the first scene becomes active; keep task windows overlapping; finish every task; and stay within the 16-task limit. Extended launch times appear under histogrammedExtendedLaunch in MXAppLaunchMetric.

Xcode Organizer Integration

Xcode Organizer shows aggregated MetricKit data across opted-in users. Use it for trend analysis alongside on-device collection routed to your own backend.

See references/metrickit-patterns.md for Organizer tab details.

Scope Boundaries

Use this skill for production MetricKit ingestion, payload export, custom MetricKit signposts, and diagnostic upload/symbolication. Route SwiftUI runtime stutters, body-update cost, identity churn, and view invalidation fixes to swiftui-performance. Route local Instruments, LLDB, Memory Graph, and xctrace workflows to debugging-instruments. When explaining production telemetry, distinguish daily metric payloads from supported diagnostics that can arrive as soon as available.

Common Mistakes

DON'T: Subscribe to MXMetricManager too late

Allocate MXMetricManager.shared and register the subscriber during app startup so the manager can accumulate reports and deliver any previously undelivered daily reports. Registering from a later view lifecycle hook is too easy to miss.

// WRONG — subscribing in a view controller
override func viewDidLoad() {
    super.viewDidLoad()
    MXMetricManager.shared.add(self)
}

// CORRECT — subscribe in application(_:didFinishLaunchingWithOptions:)
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions opts: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    MXMetricManager.shared.add(metricsSubscriber)
    return true
}

DON'T: Ignore MXDiagnosticPayload

Only handling MXMetricPayload means you miss crash, hang, and disk-write diagnostics — the most actionable data MetricKit provides.

// WRONG — only implementing metric callback
func didReceive(_ payloads: [MXMetricPayload]) { /* ... */ }

// CORRECT — implement both callbacks
func didReceive(_ payloads: [MXMetricPayload]) { /* ... */ }
func didReceive(_ payloads: [MXDiagnosticPayload]) { /* ... */ }

DON'T: Process payloads without persisting first

Do not assume callback delivery will repeat if your own processing fails. Save the raw JSON before parsing, symbolication, or upload work.

// WRONG — process inline, crash loses data
func didReceive(_ payloads: [MXDiagnosticPayload]) {
    for p in payloads {
        riskyProcessing(p)  // If this crashes, payload is gone
    }
}

// CORRECT — persist raw JSON first, then process
func didReceive(_ payloads: [MXDiagnosticPayload]) {
    for p in payloads {
        let json = p.jsonRepresentation()
        try? json.write(to: localCacheURL())   // Safe on disk
        Task.detached { self.processAsync(json) }
    }
}

DON'T: Do heavy work synchronously in didReceive

Apple documents that it is safe to process payloads on a separate thread. Keep the subscriber callback small: persist the JSON, then move expensive parsing or uploading out of the callback.

// WRONG — synchronous upload in callback
func didReceive(_ payloads: [MXMetricPayload]) {
    for p in payloads {
        let data = p.jsonRepresentation()
        URLSession.shared.uploadTask(with: request, from: data).resume()  // sync wait
    }
}

// CORRECT — persist and dispatch async
func didReceive(_ payloads: [MXMetricPayload]) {
    for p in payloads {
        let json = p.jsonRepresentation()
        persistLocally(json)
        Task.detached(priority: .utility) {
            await self.uploadToBackend(json)
        }
    }
}

DON'T: Expect immediate data in development

MetricKit aggregates data over 24-hour windows. Payloads do not arrive immediately after instrumenting. Use Xcode Organizer or simulated payloads for faster iteration during development.

DON'T: Invent MetricKit signpost IDs

MXSignpostIntervalData.makeSignpostID(log:) is not documented MetricKit API. For basic MetricKit custom metrics, create an MXMetricManager log handle and call mxSignpost(.begin/.end, log:name:) without OSSignpostID allocation or custom dso, signpostID, or format arguments.

Review Checklist

  • [ ] MXMetricManager.shared.add(subscriber) called in application(_:didFinishLaunchingWithOptions:) or App.init
  • [ ] Subscriber conforms to MXMetricManagerSubscriber and inherits NSObject
  • [ ] Both didReceive(_: [MXMetricPayload]) and didReceive(_: [MXDiagnosticPayload]) implemented
  • [ ] Raw jsonRepresentation() persisted to disk before processing
  • [ ] Heavy processing dispatched asynchronously after raw payload persistence
  • [ ] MXCallStackTree JSON uploaded with dSYMs for symbolication
  • [ ] Custom signpost metrics limited to critical code paths
  • [ ] pastPayloads and pastDiagnosticPayloads checked on launch for missed deliveries
  • [ ] Extended launch tasks call the throwing MXMetricManager type methods on the main thread and finish every started task
  • [ ] Analytics backend accepts and stores MetricKit JSON format
  • [ ] Xcode Organizer reviewed for regression trends alongside on-device data

References

Related skills

How it compares

Use metrickit for on-device Apple MetricKit patterns; use backend APM skills when the task is server-side trace aggregation instead of iOS payload collection.

FAQ

What does metrickit do?

Collect and analyze on-device performance metrics and crash diagnostics using MetricKit. Use when setting up MXMetricManager, handling MXMetricPayload or MXDiagnosticPayload, processing crash/hang/disk-write diagnostics

When should I use metrickit?

Collect and analyze on-device performance metrics and crash diagnostics using MetricKit. Use when setting up MXMetricManager, handling MXMetricPayload or MXDiagnosticPayload, processing crash/hang/disk-write diagnostics

Is metrickit safe to install?

Review the Security Audits panel on this page before installing in production.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.