Firebase Crashlytics のクラッシュ レポートのカスタマイズ

このガイドでは、Crashlytics API を使用してクラッシュ レポートをカスタマイズする方法について説明します。デフォルトでは、Crashlytics はアプリの全ユーザーを対象にプラットフォーム ネイティブ コードでのクラッシュ レポートを自動的に収集します(自動クラッシュ レポートを無効にして、ユーザーがオプトイン レポートを有効にすることもできます)。Crashlytics には、カスタムキーカスタムログユーザー IDキャッチされた例外、キャッチされていない例外という、設定不要な 5 つのロギング メカニズムが用意されています。

Flutter アプリの場合、ユーザーがアプリを再起動しなくても、致命的なイベントのレポートが Crashlytics にリアルタイムで送信されます。致命的でないイベントのレポートはディスクに書き込まれ、次の致命的イベントのレポートと一緒に送信されます。また、アプリの再起動時にも送信されます。

キャッチされなかった例外を報告する

FlutterError.onErrorFirebaseCrashlytics.instance.recordFlutterFatalError でオーバーライドすると、Flutter フレームワーク内でスローされたすべての「致命的な」エラーを自動的にキャッチできます。「致命的でない」例外もキャッチするには、FlutterError.onErrorFirebaseCrashlytics.instance.recordFlutterError でオーバーライドします。

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();
  bool weWantFatalErrorRecording = true;
  FlutterError.onError = (errorDetails) {
    if(weWantFatalErrorRecording){
      FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
    } else {
      FirebaseCrashlytics.instance.recordFlutterError(errorDetails);
    }
  };

  runApp(MyApp());
}

非同期エラー

Flutter フレームワークで非同期エラーをキャッチすることはできません。

ElevatedButton(
  onPressed: () async {
    throw Error();
  }
  ...
)

このようなエラーをキャッチするには、PlatformDispatcher.instance.onError ハンドラを使用します。

Future<void> main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    FlutterError.onError = (errorDetails) {
      FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
    };
    // Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics
    PlatformDispatcher.instance.onError = (error, stack) {
      FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
      return true;
    };
    runApp(MyApp());

}

Flutter 外部のエラー

Flutter コンテキストの外部で発生したエラーをキャッチするには、現在の Isolate にエラーリスナーをインストールします。

Isolate.current.addErrorListener(RawReceivePort((pair) async {
  final List<dynamic> errorAndStacktrace = pair;
  await FirebaseCrashlytics.instance.recordError(
    errorAndStacktrace.first,
    errorAndStacktrace.last,
    fatal: true,
  );
}).sendPort);

キャッチされた例外を報告する

Crashlytics では、アプリのクラッシュを自動的に報告するだけでなく、致命的でない例外を記録して、次に致命的なイベントを報告するときに一緒に送信できます。また、アプリの再起動時にも例外を送信できます。

recordError メソッドを使用して、致命的でない例外をアプリの catch ブロックに記録します。次に例を示します。

await FirebaseCrashlytics.instance.recordError(
  error,
  stackTrace,
  reason: 'a non-fatal error'
);

// Or you can use:
await FirebaseCrashlytics.instance.recordFlutterError(errorDetails);

また、information プロパティを使用して、発生する可能性のあるエラーの詳細をログに記録することもできます。

await FirebaseCrashlytics.instance.recordError(
  error,
  stackTrace,
  reason: 'a non-fatal error',
  information: ['further diagnostic information about the error', 'version 2.0'],
);

このような例外は、Firebase コンソールでは非致命的な問題として表示されます。問題の概要には、クラッシュの場合に通常表示されるすべての状態情報に加え、バージョンとハードウェア デバイスごとの内訳が示されます。

Crashlytics はアプリのパフォーマンスへの影響を最小限に抑えるために、専用のバックグラウンド スレッドで例外を処理します。ユーザーのネットワーク トラフィックを少なくするため、Crashlytics は必要に応じて、デバイスから送信されるレポート数にレート制限を適用します。

カスタムキーを追加する

カスタムキーを使用して、クラッシュにつながったアプリの特定の状態を把握できます。任意の Key-Value ペアをクラッシュ レポートに関連付けてから、Firebase コンソールでカスタムキーを使用してクラッシュ レポートを検索、フィルタできます。

  • Crashlytics ダッシュボードで、カスタムキーと一致する問題を検索できます。

  • コンソールで特定の問題を確認するには、各イベントに関連付けられているカスタムキーを表示します([キー] サブタブ)。カスタムキーでイベントをフィルタすることもできます(ページ上部にある [フィルタ] メニュー)。

Key-Value ペアを設定するには、setCustomKey インスタンス メソッドを使用します。次に例を示します。

// Set a key to a string.
FirebaseCrashlytics.instance.setCustomKey('str_key', 'hello');

// Set a key to a boolean.
FirebaseCrashlytics.instance.setCustomKey("bool_key", true);

// Set a key to an int.
FirebaseCrashlytics.instance.setCustomKey("int_key", 1);

// Set a key to a long.
FirebaseCrashlytics.instance.setCustomKey("int_key", 1L);

// Set a key to a float.
FirebaseCrashlytics.instance.setCustomKey("float_key", 1.0f);

// Set a key to a double.
FirebaseCrashlytics.instance.setCustomKey("double_key", 1.0);

カスタムログ メッセージを追加する

クラッシュにつながったイベントのコンテキストをさらに詳細に把握するには、Crashlytics カスタムログをアプリに追加します。Crashlytics は、ログをクラッシュ データに関連付けて、Firebase コンソールの Crashlytics の [ログ] タブに表示します。

log を使用して、問題を特定できるようにします。次に例を示します。

FirebaseCrashlytics.instance.log("Higgs-Boson detected! Bailing out");

ユーザー ID を設定する

問題を診断する際には、多くの場合、特定のクラッシュがどのユーザーで発生したかを把握すると役立ちます。Crashlytics には、クラッシュ レポート内でユーザーを匿名で識別する手段が用意されています。

レポートにユーザー ID を追加するには、各ユーザーに ID 番号、トークン、またはハッシュ値の形で一意の ID を割り当てます。

FirebaseCrashlytics.instance.setUserIdentifier("12345");

ユーザー ID を設定後にクリアする必要が生じた場合は、ID の値を空白の文字列にリセットします。ユーザー ID をクリアしても、既存の Crashlytics レコードが削除されることはありません。ユーザー ID に関連付けられたレコードを削除する必要がある場合は、Firebase サポートにお問い合わせください

オプトイン レポートを有効にする

デフォルトでは、Crashlytics は自動的にアプリの全ユーザーを対象にクラッシュ レポートを収集します。どのデータを送信するかをユーザーが細かく制御できるようにするには、オプトイン レポートを有効にします。これを行うには、自動レポートを無効にし、コード内で選択した場合のみデータを Crashlytics に送信するようにします。

  1. ネイティブでの自動収集を無効にします。

    Apple プラットフォーム

    Info.plist ファイルに新しいキーを追加します。

    • キー: FirebaseCrashlyticsCollectionEnabled
    • 値: false

    Android

    AndroidManifest.xml ファイルの application ブロックに、meta-data タグを追加して自動収集を無効にします。

    <meta-data
        android:name="firebase_crashlytics_collection_enabled"
        android:value="false" />
    
  2. 実行時に Crashlytics データ収集オーバーライドを呼び出して、選択したユーザーで収集を有効にします。

    オーバーライド値はアプリが再起動されても維持されるため、Crashlytics は自動的にレポートを収集できます。自動クラッシュ レポートを無効にするには、オーバーライド値として false を渡します。false に設定された場合、この新しい値はアプリが次回実行されるまで適用されません。

    FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
    

クラッシュ分析データを管理する

クラッシュ分析では、匿名化されたスタック トレースと他の Firebase アプリのトレースを比較して、発生した問題がより大きい傾向の一部であるかどうかが通知されるので、問題の解決に役立ちます。また、多くの問題について、クラッシュのデバッグに役立つリソースも提供されます。

クラッシュ分析は、集計されたクラッシュ データを使用して、一般的な安定性の傾向を特定します。アプリのデータを共有しない場合は、Firebase コンソールの Crashlytics 問題リストの最上部にある [クラッシュ分析情報の設定] メニューからクラッシュ分析を無効にできます。