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(
endpointBaseUrl: "https://your-backend.com",
apiKey: "your-api-key",
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
| Attribute | Description | Example | Always Present |
|---|---|---|---|
pulse.type | Instrumentation type | "device.crash" | ✅ Yes |
exception.type | Exception or signal name | "NSRangeException", "SIGABRT", "EXC_BAD_ACCESS" | ✅ Yes |
exception.message | Exception reason or diagnosis | "index 5 beyond bounds [0 .. 2]" | ✅ Yes |
exception.stacktrace | Full Apple-format crash report | Multi-line stack trace string | ✅ Yes |
thread.id | Index of crashed thread | 0, 3 | ✅ Yes |
thread.name | Thread name or queue label | "main", "com.apple.root.default-qos" | ✅ Yes |
session.id | Session ID from crash time | "f40364c92b85ec0c19c35a65be42b97f" | ✅ Yes |
screen.name | Active 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.