Skip to content

Migration Guide for KSCrash 1.x to 2.0

Gleb Linnik edited this page Oct 20, 2024 · 10 revisions

This guide provides instructions for migrating from KSCrash 1.x to version 2.0.

Support and Update Notice

Note that support for Android has been discontinued. Version 1.x will receive critical updates only until September 2025. New features will be exclusive to version 2.x.

Modules

KSCrash is now divided into several public API modules:

  • Recording (KSCrashRecording): This is a core module for crash reporting that captures all exceptions and errors. It can be used on its own.

    • Optional modules: DiscSpaceMonitor and BootTimeMonitor can be included for extended functionality. These modules are separated from KSCrashRecording because they need to capture total disk space or boot time in the crash report, which involves privacy-concerning APIs that Apple might not favor. All you need to do is import these modules via SPM or CocoaPods, and they will work automatically.
  • Reporting:

    • Filters (KSCrashFilters): Responsible for processing crash reports, including combining, filtering, and transforming crash report data into different formats for analysis and storage.
      • Demangling (KSCrashDemangleFilter): Provides demangling for both C++ and Swift symbols.
    • Sinks (KSCrashSinks): Responsible for handling the final destination of crash reports, including sending reports to servers, logging them to the console, or using any other custom sink implementation.
    • Installations (KSCrashInstallations): Responsible for setting up and configuring the crash reporting system, including setting up necessary crash report filters and sinks. This is basically how you want to use KSCrash if you don't need custom logic, which can only be implemented at the Recording module level.

Modules

SPM Imports

Targets have been modularized with simplified names, removing slash symbols to improve compatibility with various build systems. These changes necessitated an update of the imports in the source code:

  • Old Imports:

    import KSCrash_Recording
    import KSCrash_Recording_Tools
  • New Imports: Import the appropriate modules based on the specific targets defined in SPM, such as:

    import KSCrashRecording
    import KSCrashInstallations

CocoaPods Imports

CocoaPods subspecs are now aligned 1-to-1 with SPM targets for consistency.

  • Nothing has changed for importing KSCrash. Whether you're using non-modular headers, modular headers (use_modular_headers!), or frameworks, simply:

    import KSCrash

KSCrash Class API

Overview

KSCrash has undergone significant changes to improve its configuration and management. Direct property settings on KSCrash have been deprecated in favor of using configuration classes, making initialization and setup more straightforward. Instead of configuring properties directly, use KSCrashConfiguration and CrashReportStoreConfiguration to manage all related settings.

Initialization and Configuration

KSCrash now operates as a singleton; multiple instances are not supported, as they are unnecessary. The basePath property has been renamed to installPath and moved to KSCrashConfiguration.

  • Old API:

    let ksCrash = KSCrash.sharedInstance()

    or

    let ksCrash = KSCrash(basePath: "path")
  • New API:

    let ksCrash = KSCrash.shared

Example Configuration:

Below is an example of configuring KSCrash using the new configuration classes:

let config = KSCrashConfiguration()
config.monitors = .productionSafeMinimal
config.deadlockWatchdogInterval = 5.0
config.enableQueueNameSearch = true
config.enableMemoryIntrospection = true
config.doNotIntrospectClasses = ["SensitiveClass"]
config.addConsoleLogToReport = true
config.printPreviousLogOnStartup = true
config.enableSwapCxaThrow = true

let storeConfig = CrashReportStoreConfiguration()
storeConfig.reportsPath = "/path/to/reports"
storeConfig.appName = "MyApp"
storeConfig.maxReportCount = 10

// Set the report store configuration to the KSCrash configuration
config.reportStoreConfiguration = storeConfig

Installation

To install KSCrash, use the updated method:

  • Old API:
    KSCrash.sharedInstance().install()
  • New API: Use install(with:config) method to install KSCrash with the new configuration object.
    try KSCrash.shared.install(with: config)

Report Store and Sending Reports

To manage crash reports, access and configure the report store through kscrash.reportStore.

Accessing the Report Store:

let reportStore = KSCrash.shared.reportStore

Configuring Report Cleanup Policy:

Define how crash reports should be handled after being processed:

reportStore?.reportCleanupPolicy = .onSuccess

Sending Crash Reports:

Previously, the crash report sending process used a callback that included a completed flag, which could be false without an error. This ambiguity could occur due to non-erroneous conditions such as user cancellation, making it unclear whether the operation had truly failed. The updated API simplifies this by either providing reports or returning an error, leading to clearer code flow and allowing for new, modern syntax.

Sending Crash Reports:

  • Old API:

    KSCrash.sharedInstance().sendAllReports { reports, isCompleted, error in
        // Handle completion
    }
  • New API:

    reportStore?.sendAllReports(completion: { success, error in
        // Handle completion
    })

    Or use the async approach:

    try await reportStore?.sendAllReports()

Report Representation Changes

Old Usage: Previously, reports were represented as dictionaries in the KSCrash class.

if let report = KSCrash.sharedInstance().report(withID: 12345) {
    // Access report data from dictionary
    if let reportData = report[KSCrashField_System] {
        print("Crash report data: \(reportData)")
    }
}

New Usage: Now, reports are represented using more explicit types, specifically CrashReportDictionary in the CrashReportStore class.

if let report = reportStore?.report(for: 12345) {
    // Access the dictionary value of the report
    if let reportData = report.value[CrashField.system.rawValue] {
        print("Crash report data: \(reportData)")
    }
}

This new approach provides structured access to crash data with different CrashReport types, making it easier to work with crash reports and reducing the risk of runtime errors:

  • CrashReportDictionary: Represents a structured dictionary version of the crash report.
  • CrashReportString: Represents a serialized string version of the crash report.
  • CrashReportData: Represents a serialized data version of the crash report.

To access the value of a specific crash report, you can use the value property of a concrete type like CrashReportDictionary, or use the untypedValue property if accessing through the CrashReport protocol.