LoginSignup
7
3

More than 1 year has passed since last update.

[iOS] Crashlyticsとクラッシュ レポートツールを併用する話

Last updated at Posted at 2021-12-03

この記事は、ゆめみ Advent Calendar 2021 の3日目の記事です。
ちょっと間に合わなかった

はじめに

Firebase Crashlyticsはよく使われるクラッシュ検知ツールです
別のクラッシュ検知ツールからCrashlyticsへ載せ替えが必要になったのですが
一定期間は元のツールとCrashlyticsを併用して欲しい要件へ対応した際のメモです

環境

  • OS:macOS Big Sur 11.6.1
  • Swift:5.5
  • Xcode:13.0 (13A233)

現象

クラッシュレポートがCrashlyticsか他ツールのどちらかにしかレポートされない

原因

クラッシュ検知ツールは概ねtop-level error handlerを利用して、クラッシュ検知などを行なっていると考えられます
ただtop-levelとあるため、一つしか登録できず複数のクラッシュ検知を有効にした場合に、競合してしまう場合があります

対応

1. 致命的な例外(NSException)の場合


func exceptionHandler(exception: NSException) {
    UserDefaults.standard.setValue(ExceptionModel(exception), forKey: "record")
}

NSSetUncaughtExceptionHandler(exceptionHandler)

2. Swiftランタイムエラーの場合


let signalHandler : @convention(c) (Int32) -> Void = { (signal) in
    UserDefaults.standard.setValue(ExceptionModel(signal), forKey: "record")
    exit(signal)
}

for code in [SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP] {
    signal(code, signalHandler)
}

3. 起動時

if let record = UserDefaults.standard.object(forKey: "record") as? ExceptionModel {
    UserDefaults.standard.removeObject(forKey: "record")
    // TODO: Crashlytics & crash report tool recording
    print(record)
}

解説

NSSetUncaughtExceptionHandlerを使うとキャッチされなかった致命的な例外をハンドリングすることができます
しかし、これだけだとSwiftのランタイムエラーがハンドリングできないので、シグナルハンドラを利用して補足します
シグナルハンドラ内では、データの保存のみ行います
起動時に、エラーレコードがあればCrashlyticsやクラッシュ検知ツールへレコードを送信し、レコードは削除します

問題点

Crashlyticsやクラッシュ検知ツールが提供しているリッチなログ(スタックトレース等)は自力で取得しないと、レポートされません
いい感じにログ収集してくれるExceptionModelの作成が必要です

備考

実際にはPLCrashReporterなどを使うか、この様な要件は回避しましょう

参考

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3