I reverse-engineered MetricKit to get to the bottom of this. The short version is that in practice there is a "probationary period" before you get your first MXDiagnosticPayload. I suspect this is some confusion on MetricKit's part about what payloads are delivered in realtime vs what are on a 24-hour basis, but it could also be a feature.
To reproduce the "not delivered" behavior, install an app with a new bundle ID never seen before, it won't get crash reports. To reproduce the "delivered in real-time behavior", charge the device to 100%, reboot it while plugged in, and leave it locked on your desk for 15 minutes, crash reports occurring after that will be delivered in real time.
Behind the scenes, failed crash deliveries will log statements like
default 05:37:23.812310-0500 ReportCrash [bundle id] is not a MetricKit client
This is true even though, when calling MXMetricManager.shared.add(subscriber)
, metrickitd logs that you are a client.
The discrepancy seems to happen because some step inbetween these processes is disintermediated by duet scheduler (dasd
). duet considers factors like "is the device being used?" and "didn't we do this a few minutes ago?" when deciding to give cputime to tasks. So if you are currently testing this behavior, or troubleshooting why it works in one app and not in another, that actually changes the behavior which makes it very hard to understand or troubleshoot.