Firebase Crashlyticsを使ってみた

# はじめに
リリースされているアプリがcrashした時のログをFirebaseコンソールに集約することができることを知りまして実際に試してみて得た知見をまとめてみた記事です！

アプリの開発速度向上機能、グロース機能以外にも
**クオリティをサポートする機能まであるなんてステキ！**

# Firebase Crashlyticsとは？
リリースされているアプリが強制終了(以後クラッシュと呼びますね)した際のログを飛ばしFirebaseのコンソールで開発チームが確認できる機能です。

ログの種類は**クラッシュ、非致命的**の二種類を送ることができ、
非致命的に関しては開発チームで設定するだけでログの種類を分けることが可能です。

使い勝手に関してはFabricのCrashlyticsを使い慣れている方にとっては理解するのは早いと思いますし、そうでない方も仕組みは単純だと思ってますのでぜひ一度触って試してみてみると良いかもしれません！

**FabricのCrashlytics**との違いについては、
Firebaseが提供する機能の一つ**Cloud Functions**との連携があることだと考えております。
具体的に少し説明を加えると、Cloud FunctionsのEventトリガーにCrashlyticsのイベント計三種類取ることができます。

| Event名      |       内容|
|:-----------------|------------------:|
| onNew()             |              アプリで初めて問題が発生した場合 |
| onRegressed()           |            Crashlyticsで終了された後に再び発生した場合 |
| onVelocityAlert()          |            特定ビルドで統計的に有意な数のセッションがクラッシュした場合 |

使用例として一つ考えられる場合を挙げてみます。
**発生したクラッシュが初の場合Slackへ通知する**
この場合は、onNew()をトリガーにCloud Functions側でチームのSlackへ通知してあげる処理を書いてあげることで実装可能になります。

Slackへの通知文言については、公式より以下のような感じで工夫することが可能です。

```
exports.postOnNewIssue = functions.crashlytics.issue().onNew(async (issue) => {
  const issueId = issue.issueId;
  const issueTitle = issue.issueTitle;
  const appName = issue.appInfo.appName;
  const appPlatform = issue.appInfo.appPlatform;
  const latestAppVersion = issue.appInfo.latestAppVersion;

  const slackMessage = `<!here|here> There is a new issue - ${issueTitle} (${issueId}) ` +
      `in ${appName}, version ${latestAppVersion} on ${appPlatform}`;

  await notifySlack(slackMessage);
  console.log(`Posted new issue ${issueId} successfully to Slack`);
});
```

具体的な実装方法は[functions-samples](https://github.com/firebase/functions-samples/tree/Node-8/crashlytics-integration/slack-notifier)をみてみると良さそうです！

# 準備
[公式の説明](https://firebase.google.com/docs/crashlytics/get-started?hl=ja)で少し止まってしまいそうな箇所について触れてみます！

## プロジェクトのデバッグ設定を調整する

**ビルドの設定を調整して、プロジェクトのデバッグ情報の形式を変更します。**
↑
これどこ変更したら良き？
<img width="1440" alt="スクリーンショット_2019-01-04_14_22_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/2523f2af-13db-db4c-927c-7162c9c84f2e.png">

**Crashlytics のデバッグ ロギングを有効にする**
↑
これどこ変更したら有効になるの？
<img width="1440" alt="スクリーンショット_2019-01-04_14_27_19.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/6e3f25e2-4311-6c73-99be-26ccab3db1aa.png">
<img width="1440" alt="スクリーンショット_2019-01-04_14_29_34.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/c2513455-36cb-09fc-7137-515e0fa3ab18.png">

#使ってみる

一律ボタンを押した時にクラッシュする例に沿って使ってみました。

初回の通知が届いたタイミングでコンソール画面よりdSYMをアップロードしてくださーい！と言われるのでその時の対応について軽く触れときます！

**アプリのdSYMが配置されている絶対パス**
クラッシュを飛ばしているアプリのdSYMを以下の絶対パスを参考に取得し**圧縮**してからアップロードしてください！

```
/Users/[ユーザー名]/Library/Developer/Xcode/DerivedData/[プロジェクト名]-[ランダムな文字列]/Build/Products/Debug-iphoneos/[プロジェクト名].app.dSYM
```

**クラッシュ**

```swift
    @IBAction func tappedCrashButton(_ sender: Any) {
        Crashlytics.sharedInstance().crash()
    }
```

**非致命的**

```swift
    @IBAction func tappedCrashButton(_ sender: Any) {
        //非致命的
        let error = NSError(domain: "test error message", code: -1, userInfo: nil)
        Crashlytics.sharedInstance().recordError(error)
    }
```

**おまけ　AppDelegateでクラッシュした時の対応**

```swift
    @IBAction func tappedCrashButton(_ sender: Any) {
        let array = NSArray()
        let element = array.object(at: 99)
    }
```

```AppDelegate.swift
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()
        NSSetUncaughtExceptionHandler { exception in
            Crashlytics.sharedInstance().crash()
        }
        return true
    }
```

## こんな感じで確認できます!

![色々いじったらぽく表示された.png](https://qiita-image-store.s3.amazonaws.com/0/75593/e809919a-554f-6b75-65b1-46a70e2df8d9.png)

![データで端末情報とか見れるよ.png](https://qiita-image-store.s3.amazonaws.com/0/75593/aa16efd4-cbee-fab1-b507-77d0440f74ae.png)

![スタックトレースこんな感じ.png](https://qiita-image-store.s3.amazonaws.com/0/75593/ab148e01-101b-4956-92e2-d276af253dd2.png)

# 自動でクラッシュレポートを収集する方法

1.TypeScript...と書かれている箇所に`"${PODS_ROOT}/Fabric/run"`を追加
2.[Input Files]に`$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)`を追加

<img width="1001" alt="スクリーンショット 2019-01-08 19.52.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/75593/21749401-27f8-89ff-af9e-30ee0e68a026.png">

# さいごに

クラッシュしたログをFirebaseコンソールで確認できるのは便利ですね！
Firebaseが提供する機能(Cloud Functions)と連携できるのもFirebaseにCrashlyticsが追加されたことによりメリットかと思います。

次は何触ってみようかな！！！

[本記事を書く際に使用した軽いサンプルリポジトリ](https://github.com/yotsu12/FirebaseCrashlyticsSample)