Mob.PostMortem.IOS (mob v0.8.3)

Copy Markdown View Source

MetricKit-backed post-mortem ingest for iOS.

The framework attaches an MXMetricManagerSubscriber in the NIF on the first sweep/0 call, receives MetricKit payloads on a background queue thereafter, and drains the bounded in-memory queue into Mob.Defect.Capsules on Mob.Defect.Bus each time sweep/0 is called.

Scope of a payload

MetricKit hands the OS-delivered payload to the delegate once per incident class per day (approximately — the delivery cadence is under Apple's control). Each delivery may contain one or more diagnostics of different kinds:

MetricKit diagnostickind
MXCrashDiagnostic:native_crash
MXHangDiagnostic:anr (iOS's word is "hang"; the defect taxonomy uses ANR)
MXCPUExceptionDiagnostic:perf_regression
MXDiskWriteExceptionDiagnostic:perf_regression

The Payload suffix belongs on the container MXDiagnosticPayload the OS hands to didReceiveDiagnosticPayloads:, which then exposes the individual diagnostics above.

What the delivery contract looks like from Elixir

sweep/0 is safe to call at any point; MetricKit's own delivery is asynchronous and the queue accumulates until a caller drains it. A typical shape:

# In your app's on_start
def on_start do
  # ...
  Mob.PostMortem.sweep()
end

The top-level Mob.PostMortem.sweep/0 calls into this module. Nothing auto-runs — that is the framework-wide discipline: mob owns the format and the bus but never becomes the collector.

Redaction

MetricKit's MXCallStackTree carries binary UUIDs, image names and mangled symbol offsets: safe identifiers, no user data. The capsule's fingerprint key uses just the top frame's binary name and offset — enough to group the same crash across launches without embedding anything that varies per crash. The full payload JSON goes onto evidence, bounded by the capsule's existing string-truncation rule.

Platform gating

The NIF is registered on both iOS and Android (Android returns an empty list unconditionally — see android/jni/mob_nif.zig). This module additionally gates on :mob_nif.platform() == :ios so a caller on Android does no work at all, and a caller in a host test environment where the NIF is not loaded fails gracefully.

Summary

Functions

Sweep the MetricKit queue and emit a capsule for each new payload.

Functions

sweep()

@spec sweep() :: [Mob.Defect.Capsule.t()]

Sweep the MetricKit queue and emit a capsule for each new payload.

Returns the list of capsules emitted, in the order they were delivered by the OS. Empty on Android, on iOS < 14 (no MetricKit delivery API), and any time the queue was already empty since the last drain.