Skip to main content

Crash Instrumentation

Generates: Events (Log Records)

Automatically captures iOS crashes with full symbolicated stack traces, thread information, and system state.

How It Works​

The SDK integrates KSCrash to install low-level crash handlers at process startup. When a crash occurs, KSCrash records the full crash report at fault time (before the process terminates). On the next app launch, the SDK reads the report, emits a device.crash log event, and clears the stored report.

Configuration​

Crash detection is enabled by default.

Pulse.shared.initialize(

apiKey: "your-api-key",
dataCollectionState: .allowed,
instrumentations: { config in
config.crash { $0.enabled(true) } // default: true
}
)

What Gets Tracked​

  • Mach kernel exceptions (EXC_BAD_ACCESS, EXC_BAD_INSTRUCTION, etc.)
  • Fatal POSIX signals (SIGSEGV, SIGABRT, SIGBUS, etc.)
  • Objective-C uncaught exceptions (NSException)
  • C++ uncaught exceptions
  • All thread stacks at crash time
  • System state: free memory, free storage, battery level

Generated Telemetry​

Type: Log Record (Event)
Body: Exception message (may be empty for signal-based crashes)
pulse.type: device.crash
Scope Name: com.pulse.ios.sdk.crash

Attributes​

AttributeDescriptionExampleAlways Present
pulse.typeInstrumentation type"device.crash"✅ Yes
exception.typeException or signal name"NSRangeException", "SIGABRT", "EXC_BAD_ACCESS"✅ Yes
exception.messageException reason or diagnosis"index 5 beyond bounds [0 .. 2]"✅ Yes
exception.stacktraceFull Apple-format crash reportMulti-line stack trace string✅ Yes
thread.idIndex of crashed thread0, 3✅ Yes
thread.nameThread name or queue label"main", "com.apple.root.default-qos"✅ Yes
session.idSession ID from crash time"f40364c92b85ec0c19c35a65be42b97f"✅ Yes
screen.nameActive screen when crash occurred"CheckoutViewController"⚠️ If available

Crash events include resource attributes (device, OS, app version). See Global Attributes.

Sample Payload: Objective-C Exception​

{
"body": "index 5 beyond bounds [0 .. 2]",
"attributes": {
"pulse.type": "device.crash",
"exception.type": "NSRangeException",
"exception.message": "*** -[__NSArrayI objectAtIndex:]: index 5 beyond bounds [0 .. 2]",
"exception.stacktrace": "0 CoreFoundation 0x00000001803a4f74 __exceptionPreprocess\n1 libobjc.A.dylib 0x0000000180163a94 objc_exception_throw\n2 CoreFoundation 0x00000001802b1234 -[__NSArrayI objectAtIndex:]\n3 MyApp 0x00000001000012a8 -[FeedViewController loadItem] + 52\n...",
"thread.id": 0,
"thread.name": "main",
"session.id": "f40364c92b85ec0c19c35a65be42b97f",
"screen.name": "FeedViewController"
},
"scope_name": "com.pulse.ios.sdk.crash"
}

Sample Payload: Signal Crash​

{
"body": "",
"attributes": {
"pulse.type": "device.crash",
"exception.type": "EXC_BAD_ACCESS",
"exception.message": "KERN_INVALID_ADDRESS at 0x0000000000000000",
"exception.stacktrace": "0 MyApp 0x0000000100012345 -[DataManager processItem:] + 128\n1 MyApp 0x000000010001abcd -[HomeViewController refresh] + 64\n...",
"thread.id": 2,
"thread.name": "com.myapp.background-queue",
"session.id": "a1b2c3d4e5f67890a1b2c3d4e5f67890"
},
"scope_name": "com.pulse.ios.sdk.crash"
}

Important Notes​

  • Crash reports are uploaded on next launch, not at crash time. The crashed process has terminated; the SDK cannot send over the network at that moment.
  • Session stitching: The session ID from the crash is preserved and attached to the crash report, so you can find the full session in the dashboard even though the report arrives in a new session.
  • Debugger attached: Crashes cannot be tested with Xcode's debugger attached — LLDB intercepts signals before KSCrash. Test on-device without a debugger, or via TestFlight.
  • Retry: If the crash report cannot be sent on the next launch (no network), it is retried on subsequent launches until successfully delivered.

Symbolication​

Stack traces in the dashboard are symbolicated using dSYM files. Without them, you'll see raw memory addresses instead of function names.

Upload your dSYMs after every release build — see dSYM Upload.

Disabling Crash Instrumentation​

config.crash { $0.enabled(false) }

When disabled, no crash handlers are installed. You can still report non-fatal errors manually — see Error Tracking.