KSCrash Documentation

repository·master·Indexed 26 days ago

https://github.com/kstenerud/kscrash

A high-performance crash reporting library for Apple platforms (iOS, macOS, etc.) that handles Mach exceptions, signals, C++ exceptions, and Objective-C exceptions. It features on-device symbolication, detailed JSON reports, pluggable server reporting, and specialized installation types for email and console output. Includes advanced diagnostic tools such as zombie tracking, memory introspection, deadlock detection, and the KSCrashAppMemoryTracker for monitoring memory pressure.

Tokens
3.7K
Snippets
11
Records
23
Agent score
89%

What's inside KSCrash

  1. Use Namespacer to namespace public symbols

    master

    Namespacer is a tool that extracts public symbols from C, C++, and Objective-C source files using clang.cindex. It generates a header file containing #define macros that artificially namespace these symbols.

    When the macro KSCRASH_NAMESPACE is defined (e.g., #define KSCRASH_NAMESPACE _mylib), symbols like AppMemory are transformed into AppMemory_mylib in the compiled binary. This allows for symbol isolation while keeping the source code readable (except in Swift, which uses the post-processed code).

  2. Configure KSCrash in AppDelegate

    master

    To initialize the standard crash reporting system, configure a CrashInstallationStandard instance within your AppDelegate. You must specify a URL for report uploading and can optionally configure monitors (like .machException and .signal) and user alerts.

    import KSCrashInstallations
    
    class AppDelegate: UIResponder, UIApplicationDelegate {
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
            let installation = CrashInstallationStandard.shared
            installation.url = URL(string: "http://put.your.url.here")!
    
            // Install the crash reporting system
            let config = KSCrashConfiguration()
            config.monitors = [.machException, .signal]
            installation.install(with: config) // set `nil` for default config
    
            // Optional: Add an alert confirmation
            installation.addConditionalAlert(
                withTitle: "Crash Detected",
                message: "The app crashed last time it was launched. Send a crash report?",
                yesAnswer: "Sure!",
                noAnswer: "No thanks"
            )
    
            return true
        }
    }
  3. Include optional monitors (BootTime and DiscSpace)

    master

    KSCrash includes BootTimeMonitor and DiscSpaceMonitor as optional modules because they use privacy-sensitive APIs. These modules must be explicitly linked and require the developer to implement the necessary UI for user consent.

    // SPM
    .product(name: "BootTimeMonitor", package: "KSCrash"),
    .product(name: "DiscSpaceMonitor", package: "KSCrash"),
    
    // CocoaPods
    pod 'KSCrash/BootTimeMonitor'
    pod 'KSCrash/DiscSpaceMonitor'
  4. Install KSCrash via CocoaPods

    master

    Add KSCrash to your Podfile and run pod install.

    To include optional modules like BootTimeMonitor, DiscSpaceMonitor, or DemangleFilter, use the specific subspec syntax.

    # Standard installation
    pod 'KSCrash', '~> 2.5'
    
    # Optional modules
    pod 'KSCrash/BootTimeMonitor'
    pod 'KSCrash/DiscSpaceMonitor'
    pod 'KSCrash/DemangleFilter'
  5. Build and run the KSCrash SPM Namespacing Example

    master

    To run the demonstration project which shows two libraries (CrashLibA and CrashLibB) coexisting with different KSCrash instances, follow these steps:

    1. Install Tuist: https://docs.tuist.dev/en/guides/quick-start/install-tuist
    2. Run the synchronization script: ./sync.sh
    3. Navigate to the app directory: cd CrashyApp
    4. Install dependencies: tuist install
    5. Generate the Xcode project: tuist generate
    6. Build using Xcode or xcodebuild.
    ./sync.sh
    cd CrashyApp
    tuist install
    tuist generate
  6. Namespace KSCrash using Swift Package Manager

    master

    Because Swift Package Manager (SPM) targets often share a global namespace, distributing a library that uses KSCrash can lead to symbol collisions if multiple libraries in the same app use different versions of KSCrash.

    To prevent this, you can create a namespaced version of KSCrash within your own package. This involves:

    1. Creating a new Package.swift that defines your library target and a separate, namespaced KSCrash target (e.g., KSCrashLibA).
    2. Copying the unmodified KSCrash source files into your package's source directory.
    3. Setting the KSCRASH_NAMESPACE build setting in both your library target and the namespaced KSCrash target to your desired prefix (e.g., CrashLibA). This appends the prefix to all public KSCrash symbols.
    4. Generating a module.modulemap in the namespaced KSCrash target so SPM can expose the API.
    5. Merging any PrivacyInfo.xcprivacy files found in the KSCrash sources into a single file in your namespaced target's resources.
  7. Update namespaced symbols

    master
    Because Namespacer relies on scanning the source tree for public symbols, you must re-run the script whenever public symbols are added, removed, or changed in the codebase to ensure the generated header file remains in sync with the actual symbols.
  8. Install KSCrash via Swift Package Manager (SPM)

    master

    You can install KSCrash using the Xcode UI or by modifying your Package.swift file.

    Using Xcode UI

    1. In Xcode, go to File > Add Packages...
    2. Enter: https://github.com/kstenerud/KSCrash.git
    3. Select the desired version/branch.
    4. Choose your target(s) and click Add Package.

    Using Package.swift

    Add KSCrash to your dependencies and include the Installations product in your target dependencies.

    dependencies: [
        .package(url: "https://github.com/kstenerud/KSCrash.git", .upToNextMajor(from: "2.5.1"))
    ]
    
    targets: [
        .target(
            name: "YourTarget",
            dependencies: [
                .product(name: "Installations", package: "KSCrash"),
            ]),
    ]
  9. Run the Namespacer script

    master

    To generate the namespacing header file, run the namespacer.py script by providing the source tree directory and the desired output path for the header file.

    Command Syntax: python namespacer.py <source-tree> <output-header-file>

    python namespacer.py <source-tree> <output-header-file>
  10. Enable on-device symbolication

    master
    To enable on-device symbolication, you must ensure basic symbols are present in your final build. In your app's build settings, set Strip Style to Debugging Symbols. Note that this increases the final binary size by approximately 5%.
  11. Enable Zombie Tracking

    master

    KSCrash can detect zombie instances (dangling pointers to deallocated objects) by recording the address and class of deallocated objects in a cache. This feature also helps detect lost NSException objects.

    Trade-off: Adds slight overhead to object deallocation and reserves some memory.