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(
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

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.