[Firebase][iOS] Firebase Crashlytics を導入してみよう

「Firebaseを触ってみるシリーズ」です。
2019.12.13

はじめに

CX事業本部の中安です。

Firebaseを触ってみるシリーズ」の続きになります。

ここまでは

というお題で書かせていただきましたが、

今回はFabricから移行されてきた Firebase Crashlyticsを開発中のアプリに取り込んでみたので、その流れをご紹介できればと思います。

またもウダウダと書きますが、何かのお役に立てば幸いです。

Firebase Crashlytics

Firebase Crashlytics は軽量なリアルタイムのクラッシュ レポートツールで、アプリの品質を低下させる安定性の問題を追跡し、優先順位を付け、修正するのに役立ちます。Crashlytics を使用すると、クラッシュをインテリジェントにグループ化し、クラッシュにつながった状況をあぶり出すことによって、トラブルシューティングの時間を節約できます。

特定のクラッシュが多くのユーザーに影響を与えるかどうかを調べたり、問題の重大度が急激に増した場合にアラートを受け取ったりできるほか、コード内でクラッシュの原因となっている行を特定することもできます。

公式ドキュメント的にはこのような概要です。

この記事にもあるように、 Fabricからの移行期間も落ち着いてFabric Crashlyticsはそのうちに役目を終えて消えていく運命です。 今からCrashlyticsしたいという場合は、Firebase Crashlytics導入一択でよいのではないかと思います。

今回はFabricからの移行ではなく、新規で導入する場合のお話が前提です。

準備

さて、この記事は

  • Firebaseプロジェクトの作成は終わっている
  • Xcode側ではFirebaseSDKの組み込みなどが終わっている

という前提で書いていきます。

このあたりがまだという方は、ドキュメントを参照してくださいませ。

Xcode側

Cocoapods

Podfile に下記を含めて、ターミナルで pod install します

pod 'Fabric', '~> 1.10.2'
pod 'Crashlytics', '~> 3.14.0'

移行期は Podfile に色々と記載する必要があったようですが、ずいぶんと簡素にかけるようになったみたいです。

dSYMの設定

クラッシュレポートを作るのに必要なデバッグシンボルファイルのアップロードをCrashlyticsは必要としますが、 ビルド設定から首尾よく設定をしておけばそのあたりは何もせずとも吸収してくれます。

ターゲットのビルド設定から「DEBUG_INFORMATION_FORMAT」で検索し、「DWARF with dSYM File」に設定します。

スクリプトの追加

公式ドキュメントに沿っていけば大丈夫ですが(諸注意があるので気をつけてください)、文章で説明されているので画で補足してみます。

上にある手順で、New Run Script Phaseを追加したら、下記のスクリプトを設定しておきます。

"${PODS_ROOT}/Fabric/run"

「新しいビルドフェーズがプロジェクトの最後のビルドフェーズであることを確認してください。そうしないと、Crashlytics が正しく初期化されません」と書かれていますので、追加したスクリプトは一番下に置いておくことにしましょう

これによってCrashlyticsの初期化が行われるとのことで、ソースコード側で何か初期処理を書くようなことはしなくていいそうです。

Firebase側

この記事は新規導入を前提としています。 そうである場合にFirebase側で行うことはそれほどはありません。

この画面の「Crashlyticsを設定」を押して

「いいえ、新しい Firebase アプリを設定します」と答えるだけです。

あとはビルドしたアプリを実際に起動してみると、Crashlyticsのコンソール画面が表示されると思います。

クラッシュさせてみる

Crashlyticsというクラスには crash() というアプリをわざとクラッシュさせるというメソッドを用意してくれています。 丁寧にも公式ドキュメントには下記のようなサンプルソースも書いてくれています。

import UIKit
import Crashlytics

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

        let button = UIButton(type: .roundedRect)
        button.frame = CGRect(x: 20, y: 50, width: 100, height: 30)
        button.setTitle("Crash", for: [])
        button.addTarget(self, action: #selector(self.crashButtonTapped(_:)), for: .touchUpInside)
        view.addSubview(button)
    }

    @IBAction func crashButtonTapped(_ sender: AnyObject) {
        Crashlytics.sharedInstance().crash()
    }
}

やりたいことは分かるけど、ちょっと試すには冗長な気もします。

それを使わずともクラッシュさせることは簡単だと思うので、こんな感じでどうでしょう。

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        _ = [0, 1][2]
    }
}

要は配列の範囲外のインデックスを指定してわざとクラッシュさせてるだけです。

アプリで実行

XcodeのRunを押してアプリを起動してみましょう。 そして、このビューコントローラが作成されてビューができるときには、期待通りクラッシュすると思います。

しかし、その実行が"デバッグ実行"であれば、Crashlyticsには反映されないようです。 (デバック実行中に反映させるときにはこちらを参照)

一度Stopを押してデバッグ実行を停め、あらためてクラッシュさせられる場所まで進んでみてください。

結果

Firebaseからコンソールで確認してみましょう

クラッシュさせた箇所のログが出ていれば成功ですね。

早ければすぐに反映されますが、そこまでのリアルタイム性はないようです。 だいたい反映には5分以内にはされるとドキュメントには書いています。

詳細を見ると、このようにスタックトレースが確認できます。 どのバージョンのどのOSのアプリが、どの箇所で落ちているのかを追跡するのに役立ちますね。

その他、端末が縦向きだったのか横向きだった等も見ることができます。

最後に

今回は公式ドキュメントに沿って、Crashlyticsを新規導入する流れを書いてみました。

詳しくはドキュメントを参照ください