@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +266 -267
- package/package.json +2 -2
- package/pipeline/scripts/_notices.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +68 -68
- package/pipeline/skills/shared/README.md +70 -70
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -1,438 +1,255 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: metrickit-diagnostics
|
|
3
|
-
description: "
|
|
3
|
+
description: "MetricKit field telemetry from shipping apps: MXMetricManager subscribers, MXMetricPayload and MXDiagnosticPayload, crash, hang and disk-write call stacks in MXCallStackTree, custom mxSignpost metrics, extended launch measurement, exporting payloads to an analytics backend. Use when setting up MetricKit, fixing mxSignpost or extended-launch code, or uploading field diagnostics."
|
|
4
4
|
metadata:
|
|
5
|
-
source:
|
|
5
|
+
source: multi-agent-pipeline
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# MetricKit
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- [Common Mistakes](#common-mistakes)
|
|
29
|
-
- [Review Checklist](#review-checklist)
|
|
30
|
-
- [References](#references)
|
|
31
|
-
|
|
32
|
-
## Subscriber Setup
|
|
33
|
-
|
|
34
|
-
Register a subscriber as early as possible - ideally in
|
|
35
|
-
`application(_:didFinishLaunchingWithOptions:)` or `App.init`. MetricKit
|
|
36
|
-
starts accumulating reports after the first access to `MXMetricManager.shared`.
|
|
37
|
-
When backfilling, state precisely that `pastPayloads` and
|
|
38
|
-
`pastDiagnosticPayloads` return reports generated since the last allocation of
|
|
39
|
-
the shared manager instance.
|
|
10
|
+
MetricKit reports how the app behaves on real devices. Two kinds of payload
|
|
11
|
+
arrive:
|
|
12
|
+
|
|
13
|
+
- **Metric payloads**, aggregated daily: CPU, memory, launch and resume
|
|
14
|
+
time, hang rate, scroll hitches, network use and more.
|
|
15
|
+
- **Diagnostic payloads**: crashes, hangs, CPU exceptions and disk-write
|
|
16
|
+
exceptions, each with a call-stack tree.
|
|
17
|
+
|
|
18
|
+
## Registering a subscriber
|
|
19
|
+
|
|
20
|
+
MetricKit starts gathering data the first time the app touches
|
|
21
|
+
`MXMetricManager.shared`, so register as early as launch allows:
|
|
22
|
+
`application(_:didFinishLaunchingWithOptions:)` in UIKit, `App.init` in
|
|
23
|
+
SwiftUI.
|
|
24
|
+
|
|
25
|
+
`pastPayloads` and `pastDiagnosticPayloads` hold the reports produced since
|
|
26
|
+
the shared manager instance was last allocated. Use exactly that wording when
|
|
27
|
+
you describe a backfill; they are not "everything MetricKit ever collected".
|
|
40
28
|
|
|
41
29
|
```swift
|
|
42
30
|
import MetricKit
|
|
43
31
|
|
|
44
|
-
final class
|
|
45
|
-
static let shared =
|
|
32
|
+
final class FieldTelemetry: NSObject, MXMetricManagerSubscriber, Sendable {
|
|
33
|
+
static let shared = FieldTelemetry()
|
|
46
34
|
|
|
47
|
-
func
|
|
35
|
+
func start() {
|
|
48
36
|
let manager = MXMetricManager.shared
|
|
49
37
|
manager.add(self)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
processMetricPayloads(manager.pastPayloads)
|
|
53
|
-
processDiagnosticPayloads(manager.pastDiagnosticPayloads)
|
|
38
|
+
store(manager.pastPayloads)
|
|
39
|
+
store(manager.pastDiagnosticPayloads)
|
|
54
40
|
}
|
|
55
41
|
|
|
56
|
-
func
|
|
42
|
+
func stop() {
|
|
57
43
|
MXMetricManager.shared.remove(self)
|
|
58
44
|
}
|
|
59
45
|
|
|
60
46
|
func didReceive(_ payloads: [MXMetricPayload]) {
|
|
61
|
-
|
|
47
|
+
store(payloads)
|
|
62
48
|
}
|
|
63
49
|
|
|
64
50
|
func didReceive(_ payloads: [MXDiagnosticPayload]) {
|
|
65
|
-
|
|
51
|
+
store(payloads)
|
|
66
52
|
}
|
|
53
|
+
|
|
54
|
+
private func store(_ payloads: [MXMetricPayload]) { /* see Exporting */ }
|
|
55
|
+
private func store(_ payloads: [MXDiagnosticPayload]) { /* see Exporting */ }
|
|
67
56
|
}
|
|
68
57
|
```
|
|
69
58
|
|
|
70
|
-
### UIKit Registration
|
|
71
|
-
|
|
72
59
|
```swift
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
77
|
-
MetricsSubscriber.shared.subscribe()
|
|
60
|
+
// UIKit
|
|
61
|
+
func application(_ application: UIApplication,
|
|
62
|
+
didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
|
63
|
+
FieldTelemetry.shared.start()
|
|
78
64
|
return true
|
|
79
65
|
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### SwiftUI Registration
|
|
83
66
|
|
|
84
|
-
|
|
67
|
+
// SwiftUI
|
|
85
68
|
@main
|
|
86
|
-
struct
|
|
87
|
-
init() {
|
|
88
|
-
MetricsSubscriber.shared.subscribe()
|
|
89
|
-
}
|
|
69
|
+
struct TrailheadApp: App {
|
|
70
|
+
init() { FieldTelemetry.shared.start() }
|
|
90
71
|
var body: some Scene {
|
|
91
|
-
WindowGroup {
|
|
72
|
+
WindowGroup { RootView() }
|
|
92
73
|
}
|
|
93
74
|
}
|
|
94
75
|
```
|
|
95
76
|
|
|
96
|
-
##
|
|
77
|
+
## Metric payloads
|
|
97
78
|
|
|
98
|
-
`MXMetricPayload`
|
|
99
|
-
|
|
100
|
-
|
|
79
|
+
An `MXMetricPayload` shows up roughly once every 24 hours. If earlier
|
|
80
|
+
deliveries were missed, one callback can carry several. Each payload has
|
|
81
|
+
`timeStampBegin`, `timeStampEnd` and `latestApplicationVersion`. Save
|
|
82
|
+
`jsonRepresentation()` first, then queue any processing.
|
|
101
83
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
for payload in payloads {
|
|
105
|
-
let begin = payload.timeStampBegin
|
|
106
|
-
let end = payload.timeStampEnd
|
|
107
|
-
let version = payload.latestApplicationVersion
|
|
108
|
-
|
|
109
|
-
// Persist raw JSON before processing
|
|
110
|
-
let jsonData = payload.jsonRepresentation()
|
|
111
|
-
persistPayload(jsonData, from: begin, to: end)
|
|
112
|
-
|
|
113
|
-
enqueueMetricProcessing(jsonData)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
```
|
|
84
|
+
Available since macOS 10.15, iOS and iPadOS 13, Mac Catalyst 13.1 and
|
|
85
|
+
visionOS 1.
|
|
117
86
|
|
|
118
|
-
|
|
119
|
-
Mac Catalyst 13.1+, macOS 10.15+, visionOS 1.0+
|
|
87
|
+
## Diagnostic payloads
|
|
120
88
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
report.
|
|
89
|
+
`MXDiagnosticPayload` groups several diagnostic kinds: crashes, hangs,
|
|
90
|
+
CPU exceptions, excessive disk writes and, on platforms that support them,
|
|
91
|
+
slow app launches. Since iOS 15 and
|
|
92
|
+
macOS 12 supported diagnostics are delivered as soon as they are available
|
|
93
|
+
instead of waiting for the daily report.
|
|
127
94
|
|
|
128
95
|
```swift
|
|
129
96
|
func didReceive(_ payloads: [MXDiagnosticPayload]) {
|
|
130
97
|
for payload in payloads {
|
|
131
|
-
|
|
132
|
-
persistPayload(jsonData)
|
|
133
|
-
enqueueDiagnosticProcessing(jsonData)
|
|
98
|
+
persist(payload.jsonRepresentation()) // durable first
|
|
134
99
|
}
|
|
100
|
+
Task.detached(priority: .utility) { await DiagnosticsQueue.shared.drain() }
|
|
135
101
|
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
In the background processor, inspect the typed diagnostic arrays after the raw
|
|
139
|
-
payload is durable:
|
|
140
102
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if let diskWrites = payload.diskWriteExceptionDiagnostics {
|
|
154
|
-
for diskWrite in diskWrites {
|
|
155
|
-
handleDiskWrite(diskWrite)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
if let cpuExceptions = payload.cpuExceptionDiagnostics {
|
|
159
|
-
for cpuException in cpuExceptions {
|
|
160
|
-
handleCPUException(cpuException)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
#if os(iOS) || targetEnvironment(macCatalyst) || os(visionOS)
|
|
164
|
-
if #available(iOS 16.0, macCatalyst 16.0, visionOS 1.0, *),
|
|
165
|
-
let launchDiagnostics = payload.appLaunchDiagnostics {
|
|
166
|
-
for launchDiagnostic in launchDiagnostics {
|
|
167
|
-
handleSlowLaunch(launchDiagnostic)
|
|
168
|
-
}
|
|
103
|
+
func summarize(_ payload: MXDiagnosticPayload) -> [String: Int] {
|
|
104
|
+
var counts: [String: Int] = [
|
|
105
|
+
"crash": payload.crashDiagnostics?.count ?? 0,
|
|
106
|
+
"hang": payload.hangDiagnostics?.count ?? 0,
|
|
107
|
+
"diskWrite": payload.diskWriteExceptionDiagnostics?.count ?? 0,
|
|
108
|
+
"cpu": payload.cpuExceptionDiagnostics?.count ?? 0
|
|
109
|
+
]
|
|
110
|
+
#if os(iOS) || os(visionOS) || targetEnvironment(macCatalyst)
|
|
111
|
+
if #available(iOS 16, macCatalyst 16, visionOS 1, *) {
|
|
112
|
+
counts["launch"] = payload.appLaunchDiagnostics?.count ?? 0
|
|
169
113
|
}
|
|
170
114
|
#endif
|
|
115
|
+
return counts
|
|
171
116
|
}
|
|
172
117
|
```
|
|
173
118
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
requires iOS 16.0+, iPadOS 16.0+, Mac Catalyst 16.0+, or visionOS 1.0+.
|
|
119
|
+
The callback only persists and schedules; inspecting the typed arrays
|
|
120
|
+
happens later, in the background worker.
|
|
177
121
|
|
|
178
|
-
|
|
122
|
+
| Type | iOS / iPadOS | Mac Catalyst | macOS | visionOS |
|
|
123
|
+
|---|---|---|---|---|
|
|
124
|
+
| `MXDiagnosticPayload` | 14 | 14 | 12 | 1 |
|
|
125
|
+
| `appLaunchDiagnostics` | 16 | 16 | not available | 1 |
|
|
126
|
+
| `MXCallStackTree` | 14 | 14 | 12 | 1 |
|
|
179
127
|
|
|
180
|
-
|
|
128
|
+
## Metrics worth reading
|
|
181
129
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
130
|
+
| Payload property | Type | Useful values |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `applicationLaunchMetrics` | `MXAppLaunchMetric` | `histogrammedTimeToFirstDraw`, `histogrammedOptimizedTimeToFirstDraw`, `histogrammedApplicationResumeTime`, `histogrammedExtendedLaunch` |
|
|
133
|
+
| `applicationTimeMetrics` | `MXAppRunTimeMetric` | `cumulativeForegroundTime`, `cumulativeBackgroundTime`, `cumulativeBackgroundAudioTime`, `cumulativeBackgroundLocationTime` (all `Measurement<UnitDuration>`) |
|
|
134
|
+
| `cpuMetrics` | `MXCPUMetric` | `cumulativeCPUTime` (duration) |
|
|
135
|
+
| `memoryMetrics` | `MXMemoryMetric` | `peakMemoryUsage` (`UnitInformationStorage`) |
|
|
136
|
+
| `applicationResponsivenessMetrics` | `MXAppResponsivenessMetric` | `histogrammedApplicationHangTime` |
|
|
137
|
+
| `animationMetrics` | `MXAnimationMetric` | `scrollHitchTimeRatio` |
|
|
138
|
+
| `networkTransferMetrics` | `MXNetworkTransferMetric` | `cumulativeWifiUpload`, `cumulativeWifiDownload`, `cumulativeCellularUpload`, `cumulativeCellularDownload` (`UnitInformationStorage`) |
|
|
139
|
+
| `applicationExitMetrics` | `MXAppExitMetric` | `foregroundExitData`, `backgroundExitData`: normal, abnormal, watchdog, memory-limit and other exit counts |
|
|
190
140
|
|
|
191
|
-
|
|
141
|
+
## Call-stack trees
|
|
192
142
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
let bg = runTime.cumulativeBackgroundTime
|
|
197
|
-
let bgAudio = runTime.cumulativeBackgroundAudioTime
|
|
198
|
-
let bgLocation = runTime.cumulativeBackgroundLocationTime
|
|
199
|
-
}
|
|
200
|
-
```
|
|
143
|
+
Every diagnostic carries an `MXCallStackTree`. Its `jsonRepresentation()`
|
|
144
|
+
lists the frames; symbolicate them with `atos`, or upload the JSON together
|
|
145
|
+
with the build's dSYMs to your crash service.
|
|
201
146
|
|
|
202
|
-
|
|
147
|
+
## Custom signpost metrics
|
|
203
148
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if let memory = payload.memoryMetrics {
|
|
209
|
-
let peakMemory = memory.peakMemoryUsage // Measurement<UnitInformationStorage>
|
|
210
|
-
}
|
|
211
|
-
if let responsiveness = payload.applicationResponsivenessMetrics {
|
|
212
|
-
let hangTime = responsiveness.histogrammedApplicationHangTime
|
|
213
|
-
}
|
|
214
|
-
if let animation = payload.animationMetrics {
|
|
215
|
-
let scrollHitchRate = animation.scrollHitchTimeRatio // Measurement<Unit>
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Network and Cellular
|
|
149
|
+
Emit `mxSignpost` on a log handle from `MXMetricManager.makeLogHandle(category:)`.
|
|
150
|
+
Leave `dso`, `signpostID` and `format` at their defaults. The basic pattern
|
|
151
|
+
needs no `OSSignpostID`; create one only to tell apart intervals with the
|
|
152
|
+
same name that overlap.
|
|
220
153
|
|
|
221
154
|
```swift
|
|
222
|
-
|
|
223
|
-
let wifiUp = network.cumulativeWifiUpload // Measurement<UnitInformationStorage>
|
|
224
|
-
let wifiDown = network.cumulativeWifiDownload
|
|
225
|
-
let cellUp = network.cumulativeCellularUpload
|
|
226
|
-
let cellDown = network.cumulativeCellularDownload
|
|
227
|
-
}
|
|
228
|
-
```
|
|
155
|
+
import MetricKit
|
|
229
156
|
|
|
230
|
-
|
|
157
|
+
let checkoutLog = MXMetricManager.makeLogHandle(category: "Checkout")
|
|
231
158
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
// Inspect normal, abnormal, watchdog, memory, etc.
|
|
159
|
+
func placeOrder(_ cart: Cart) async throws {
|
|
160
|
+
mxSignpost(.begin, log: checkoutLog, name: "PlaceOrder")
|
|
161
|
+
defer { mxSignpost(.end, log: checkoutLog, name: "PlaceOrder") }
|
|
162
|
+
try await orderService.submit(cart)
|
|
237
163
|
}
|
|
238
164
|
```
|
|
239
165
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
166
|
+
The aggregated numbers come back in the daily payload under
|
|
167
|
+
`MXMetricPayload.signpostMetrics`. Say so explicitly when reviewing or fixing
|
|
168
|
+
signpost code, because people often look for them in diagnostics.
|
|
243
169
|
|
|
244
|
-
|
|
170
|
+
## Exporting
|
|
245
171
|
|
|
246
|
-
|
|
247
|
-
|
|
172
|
+
Both payload classes provide `jsonRepresentation()`. Write the raw JSON to
|
|
173
|
+
disk before any parsing or upload, and read the past-payload properties at
|
|
174
|
+
launch in case callbacks were missed. Upload code is in
|
|
175
|
+
[MetricKit patterns](references/metrickit-patterns.md).
|
|
248
176
|
|
|
249
|
-
##
|
|
177
|
+
## Extended launch measurement
|
|
250
178
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
instrumentation. When correcting custom signpost code, explicitly name
|
|
256
|
-
`MXMetricPayload.signpostMetrics` so the caller knows where the data lands.
|
|
257
|
-
Do not allocate or pass an `OSSignpostID` for the basic MetricKit pattern; use
|
|
258
|
-
the defaulted `mxSignpost(.begin/.end, log:name:)` calls unless there is a
|
|
259
|
-
specific overlapping-interval reason to do otherwise.
|
|
179
|
+
Lets launch time include setup that happens after the first frame, such as
|
|
180
|
+
opening a database. Available on iOS and iPadOS 16+, Mac Catalyst 16+,
|
|
181
|
+
macOS 13+ and visionOS 1+. Both calls are throwing **type** methods on
|
|
182
|
+
`MXMetricManager`, not methods on the shared instance.
|
|
260
183
|
|
|
261
184
|
```swift
|
|
262
|
-
let
|
|
263
|
-
mxSignpost(.begin, log: metricLog, name: "DataFetch")
|
|
264
|
-
defer { mxSignpost(.end, log: metricLog, name: "DataFetch") }
|
|
265
|
-
|
|
266
|
-
let data = try await fetchData()
|
|
267
|
-
```
|
|
185
|
+
let warmCatalog = MXLaunchTaskID("com.example.trailhead.catalog")
|
|
268
186
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
persist raw JSON to disk before processing. Use `pastPayloads` and
|
|
275
|
-
`pastDiagnosticPayloads` on launch to retrieve reports generated since the last
|
|
276
|
-
allocation of the shared manager instance.
|
|
277
|
-
|
|
278
|
-
See [references/metrickit-patterns.md](references/metrickit-patterns.md) for export code and past payload retrieval.
|
|
279
|
-
|
|
280
|
-
## Extended Launch Measurement
|
|
281
|
-
|
|
282
|
-
Track post-first-draw setup work as part of the launch metric on iOS 16+,
|
|
283
|
-
iPadOS 16+, Mac Catalyst 16+, macOS 13+, and visionOS 1+:
|
|
284
|
-
|
|
285
|
-
```swift
|
|
286
|
-
let taskID = MXLaunchTaskID("com.example.app.loadDatabase")
|
|
287
|
-
try MXMetricManager.extendLaunchMeasurement(forTaskID: taskID)
|
|
288
|
-
defer { try? MXMetricManager.finishExtendedLaunchMeasurement(forTaskID: taskID) }
|
|
289
|
-
restoreCachedState()
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
When correcting extended launch code, include the whole operational contract:
|
|
293
|
-
availability is iOS/iPadOS/Mac Catalyst 16+, macOS 13+, and visionOS 1+; call
|
|
294
|
-
the throwing `MXMetricManager` type methods on the main thread; start the first
|
|
295
|
-
task before the first scene becomes active; keep task windows overlapping;
|
|
296
|
-
finish every task; and stay within the 16-task limit. Extended launch times
|
|
297
|
-
appear under `histogrammedExtendedLaunch` in `MXAppLaunchMetric`.
|
|
298
|
-
|
|
299
|
-
## Xcode Organizer Integration
|
|
300
|
-
|
|
301
|
-
Xcode Organizer shows aggregated MetricKit data across opted-in users. Use it for trend analysis alongside on-device collection routed to your own backend.
|
|
302
|
-
|
|
303
|
-
See [references/metrickit-patterns.md](references/metrickit-patterns.md) for Organizer tab details.
|
|
304
|
-
|
|
305
|
-
## Scope Boundaries
|
|
306
|
-
|
|
307
|
-
Use this skill for production MetricKit ingestion, payload export, custom
|
|
308
|
-
MetricKit signposts, and diagnostic upload/symbolication. Route SwiftUI runtime
|
|
309
|
-
stutters, body-update cost, identity churn, and view invalidation fixes to
|
|
310
|
-
`swiftui-performance`. Route local Instruments, LLDB, Memory Graph, and
|
|
311
|
-
`xctrace` workflows to `debugging-instruments`. When explaining production
|
|
312
|
-
telemetry, distinguish daily metric payloads from supported diagnostics that
|
|
313
|
-
can arrive as soon as available.
|
|
314
|
-
|
|
315
|
-
## Common Mistakes
|
|
316
|
-
|
|
317
|
-
### DON'T: Subscribe to MXMetricManager too late
|
|
318
|
-
|
|
319
|
-
Allocate `MXMetricManager.shared` and register the subscriber during app startup
|
|
320
|
-
so the manager can accumulate reports and deliver any previously undelivered
|
|
321
|
-
daily reports. Registering from a later view lifecycle hook is too easy to miss.
|
|
322
|
-
|
|
323
|
-
```swift
|
|
324
|
-
// WRONG - subscribing in a view controller
|
|
325
|
-
override func viewDidLoad() {
|
|
326
|
-
super.viewDidLoad()
|
|
327
|
-
MXMetricManager.shared.add(self)
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// CORRECT - subscribe in application(_:didFinishLaunchingWithOptions:)
|
|
331
|
-
func application(
|
|
332
|
-
_ application: UIApplication,
|
|
333
|
-
didFinishLaunchingWithOptions opts: [UIApplication.LaunchOptionsKey: Any]?
|
|
334
|
-
) -> Bool {
|
|
335
|
-
MXMetricManager.shared.add(metricsSubscriber)
|
|
336
|
-
return true
|
|
187
|
+
@MainActor
|
|
188
|
+
func prepareCatalog() async throws {
|
|
189
|
+
try MXMetricManager.extendLaunchMeasurement(forTaskID: warmCatalog)
|
|
190
|
+
defer { try? MXMetricManager.finishExtendedLaunchMeasurement(forTaskID: warmCatalog) }
|
|
191
|
+
try await catalog.openStore()
|
|
337
192
|
}
|
|
338
193
|
```
|
|
339
194
|
|
|
340
|
-
|
|
195
|
+
Rules: make both calls on the main thread; begin the earliest task while no
|
|
196
|
+
scene is active yet; tasks may overlap; finish every task you start; at most
|
|
197
|
+
16 tasks. The result lands in `histogrammedExtendedLaunch` on
|
|
198
|
+
`MXAppLaunchMetric`.
|
|
341
199
|
|
|
342
|
-
|
|
343
|
-
diagnostics - the most actionable data MetricKit provides.
|
|
200
|
+
## Xcode Organizer
|
|
344
201
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
func didReceive(_ payloads: [MXMetricPayload]) { /* ... */ }
|
|
202
|
+
Organizer shows MetricKit data aggregated across users who share analytics.
|
|
203
|
+
Use it for trends and regressions, and your own collection for detail.
|
|
348
204
|
|
|
349
|
-
|
|
350
|
-
func didReceive(_ payloads: [MXMetricPayload]) { /* ... */ }
|
|
351
|
-
func didReceive(_ payloads: [MXDiagnosticPayload]) { /* ... */ }
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### DON'T: Process payloads without persisting first
|
|
355
|
-
|
|
356
|
-
Do not assume callback delivery will repeat if your own processing fails. Save
|
|
357
|
-
the raw JSON before parsing, symbolication, or upload work.
|
|
358
|
-
|
|
359
|
-
```swift
|
|
360
|
-
// WRONG - process inline, crash loses data
|
|
361
|
-
func didReceive(_ payloads: [MXDiagnosticPayload]) {
|
|
362
|
-
for p in payloads {
|
|
363
|
-
riskyProcessing(p) // If this crashes, payload is gone
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// CORRECT - persist raw JSON first, then process
|
|
368
|
-
func didReceive(_ payloads: [MXDiagnosticPayload]) {
|
|
369
|
-
for p in payloads {
|
|
370
|
-
let json = p.jsonRepresentation()
|
|
371
|
-
try? json.write(to: localCacheURL()) // Safe on disk
|
|
372
|
-
Task.detached { self.processAsync(json) }
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
### DON'T: Do heavy work synchronously in didReceive
|
|
205
|
+
## Scope
|
|
378
206
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
or uploading out of the callback.
|
|
382
|
-
|
|
383
|
-
```swift
|
|
384
|
-
// WRONG - synchronous upload in callback
|
|
385
|
-
func didReceive(_ payloads: [MXMetricPayload]) {
|
|
386
|
-
for p in payloads {
|
|
387
|
-
let data = p.jsonRepresentation()
|
|
388
|
-
URLSession.shared.uploadTask(with: request, from: data).resume() // sync wait
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// CORRECT - persist and dispatch async
|
|
393
|
-
func didReceive(_ payloads: [MXMetricPayload]) {
|
|
394
|
-
for p in payloads {
|
|
395
|
-
let json = p.jsonRepresentation()
|
|
396
|
-
persistLocally(json)
|
|
397
|
-
Task.detached(priority: .utility) {
|
|
398
|
-
await self.uploadToBackend(json)
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
```
|
|
207
|
+
In scope: ingesting production payloads, exporting them, custom signposts,
|
|
208
|
+
uploading and symbolicating diagnostics. Out of scope:
|
|
403
209
|
|
|
404
|
-
|
|
210
|
+
- SwiftUI stutters, expensive `body` evaluation, identity or invalidation
|
|
211
|
+
fixes: `swiftui-performance`
|
|
212
|
+
- Local Instruments sessions, LLDB, Memory Graph, `xctrace`: `debugging-instruments`
|
|
405
213
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
214
|
+
Keep the delivery model straight: metric payloads are daily aggregates;
|
|
215
|
+
diagnostics may arrive right away. MetricKit is a production signal, not an
|
|
216
|
+
instant local debugging tool.
|
|
409
217
|
|
|
410
|
-
|
|
218
|
+
## Common mistakes
|
|
411
219
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
220
|
+
- **Subscribing late**, for example in a view controller's `viewDidLoad`.
|
|
221
|
+
Subscribe at launch.
|
|
222
|
+
- **Handling only metric payloads.** Crashes, hangs and disk-write
|
|
223
|
+
exceptions arrive through the diagnostic callback.
|
|
224
|
+
- **Processing before saving.** If parsing crashes, the payload may never be
|
|
225
|
+
redelivered. Write the JSON to a local cache first.
|
|
226
|
+
- **Heavy work in the callback.** Apple documents that processing on another
|
|
227
|
+
thread is safe; keep the callback short and move uploads to
|
|
228
|
+
`Task.detached(priority: .utility)`.
|
|
229
|
+
- **Expecting payloads during development.** Metrics aggregate over 24 hours;
|
|
230
|
+
use Organizer, or Xcode's Debug > Simulate MetricKit Payloads.
|
|
231
|
+
- **Calling `MXSignpostIntervalData.makeSignpostID(log:)`.** It is not a
|
|
232
|
+
documented MetricKit API.
|
|
416
233
|
|
|
417
|
-
## Review
|
|
234
|
+
## Review checklist
|
|
418
235
|
|
|
419
|
-
- [ ] `MXMetricManager.shared.add(
|
|
420
|
-
- [ ] Subscriber
|
|
421
|
-
- [ ] Both `didReceive
|
|
422
|
-
- [ ]
|
|
423
|
-
- [ ] Heavy
|
|
424
|
-
- [ ]
|
|
425
|
-
- [ ] Custom
|
|
426
|
-
- [ ]
|
|
427
|
-
- [ ] Extended launch
|
|
428
|
-
- [ ]
|
|
429
|
-
- [ ]
|
|
236
|
+
- [ ] `MXMetricManager.shared.add(_:)` runs at launch or in `App.init`
|
|
237
|
+
- [ ] Subscriber is an `NSObject` conforming to `MXMetricManagerSubscriber`
|
|
238
|
+
- [ ] Both `didReceive` callbacks implemented
|
|
239
|
+
- [ ] Payload JSON persisted before processing
|
|
240
|
+
- [ ] Heavy work happens asynchronously after persistence
|
|
241
|
+
- [ ] Call-stack JSON uploaded along with dSYMs
|
|
242
|
+
- [ ] Custom signposts limited to critical paths
|
|
243
|
+
- [ ] Past payloads read at launch
|
|
244
|
+
- [ ] Extended launch calls the static `try` methods from the main thread and ends each task it began
|
|
245
|
+
- [ ] Backend stores the raw MetricKit JSON
|
|
246
|
+
- [ ] Organizer checked for regressions
|
|
430
247
|
|
|
431
248
|
## References
|
|
432
249
|
|
|
433
|
-
-
|
|
434
|
-
-
|
|
435
|
-
-
|
|
436
|
-
-
|
|
437
|
-
-
|
|
438
|
-
-
|
|
250
|
+
- [MetricKit patterns](references/metrickit-patterns.md): crash and hang handlers, signposts end to end, export and upload, past payloads, extended launch rules, Organizer tabs, documentation links
|
|
251
|
+
- https://developer.apple.com/documentation/metrickit
|
|
252
|
+
- https://developer.apple.com/documentation/metrickit/mxmetricmanager
|
|
253
|
+
- https://developer.apple.com/documentation/metrickit/mxmetricmanagersubscriber
|
|
254
|
+
- https://developer.apple.com/documentation/metrickit/mxmetricpayload
|
|
255
|
+
- https://developer.apple.com/documentation/metrickit/mxdiagnosticpayload
|