🔥

【初心者向け】Firebase Crashlyticsが正常に動いているか確認する手順

に公開

こんにちは、ワニかず@40歳 出戻りエンジニアです。

FlutterでFirebase Crashlyticsにエラーの情報が表示されるよう
コードを用意したものの、正常に動いているのかどうかを確認するのに
少し時間がかかりましたので、その確認方法をまとめました。

前提

  • FlutterのアプリとFirebaseの疎通が取れていること(FirestoreやAuthenticationなどで)

クラッシュが起きる前の状態

以下のように、左側のメニューから「Crashlytics」を選択すると、

まだ何も起きていないので、
「クラッシュを待機しています。」
と記載されており、何も表示されていません。

一生待機していたほしい(一生クラッシュしないでほしい)
と誰しも思うと思うのですが、
いざクラッシュしたときに、何も追跡できないと大変なので、
ちゃんとクラッシュした情報がここの表示されるか確認します。

実装したコード

  1. app_logger.dart
app_logger.dart
import 'package:flutter/foundation.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_core/firebase_core.dart';

class AppLogger {
  static bool _initialized = false;
  
  // ログレベル定義
  static const int DEBUG = 0;
  static const int INFO = 1;
  static const int WARNING = 2;
  static const int ERROR = 3;
  
  static int currentLevel = kDebugMode ? DEBUG : INFO;
  
  // Crashlyticsの初期化
  static Future<void> initialize() async {
    if (_initialized) return;
    
    // Firebaseが初期化されていることを確認
    if (Firebase.apps.isEmpty) {
      await Firebase.initializeApp();
    }
    
    // Flutterのエラーを自動的にCrashlyticsに送信する
    FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
    
    // 非同期エラーをキャッチするためのハンドラも設定できます
    PlatformDispatcher.instance.onError = (error, stack) {
      FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
      return true;
    };
    
    _initialized = true;
    
    i('AppLogger initialized with Crashlytics');
  }
  
  // 以下、従来のログメソッド
  static void d(String message) {
    _ensureInitialized();
    if (currentLevel <= DEBUG) {
      print('🔍 DEBUG: $message');
    }
  }
  
  static void i(String message) {
    _ensureInitialized();
    if (currentLevel <= INFO) {
      print('ℹ️ INFO: $message');
      FirebaseCrashlytics.instance.log(message);
    }
  }
  
  static void w(String message) {
    _ensureInitialized();
    if (currentLevel <= WARNING) {
      print('⚠️ WARNING: $message');
      FirebaseCrashlytics.instance.log('WARNING: $message');
    }
  }
  
  static void e(String message, [dynamic error, StackTrace? stackTrace]) {
    _ensureInitialized();
    if (currentLevel <= ERROR) {
      print('🔴 ERROR: $message');
      if (error != null) {
        print(error);
        if (stackTrace != null) {
          FirebaseCrashlytics.instance.recordError(error, stackTrace);
        }
      } else {
        FirebaseCrashlytics.instance.log('ERROR: $message');
      }
    }
  }
  
  // 初期化されていることを確認する内部メソッド
  static void _ensureInitialized() {
    if (!_initialized) {
      print('⚠️ AppLogger used before initialization. Call AppLogger.initialize() first.');
      // 非同期で初期化を試みる
      initialize();
    }
  }
  
  // その他のメソッド...
}
  1. main.dart
main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await AppLogger.initialize();
  
  // その他の初期化処理
  
  runApp(MyApp());
}
  1. pubspec.yaml
pubspec.yaml
dependencies:
 flutter:
   sdk: flutter
 firebase_core: ^latest_version
 firebase_crashlytics: ^latest_version  # この行を追加
 # 他の依存関係...

latest_version の部分は、最新のバージョン番号(例: ^4.3.4)に置き換えてください。

Crashlyticsの動作確認方法

非致命的エラーを記録してテストする
main.dartに、

main.dart
import 'package:firebase_crashlytics/firebase_crashlytics.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await AppLogger.initialize();
  
  try {
     throw Exception('これはテストエラーです');
  } catch (e, stack) {
     // ここが実行されるのを確認する
     FirebaseCrashlytics.instance.recordError(e, stack, reason: 'テスト目的');
  }
  
  runApp(MyApp());
}

クラッシュが検知されると?

以下のような画面になります。

CrashlyticsとAnalyticsの使い分け

Crashlytics

  • 主な目的: アプリのクラッシュや深刻なエラーを検出し、診断情報を提供する
  • メリット:
    • クラッシュの原因を特定しやすい
    • スタックトレースや発生状況の詳細を提供
    • 開発者視点でのアプリ安定性の把握に最適
  • 実装の優先度: 安定性が重視されるアプリでは高い

Analytics

  • 主な目的: ユーザー行動や使用パターンを追跡し、アプリのパフォーマンスを分析
  • メリット:
    • ユーザーの行動パターンを把握できる
    • コンバージョンや目標達成率を測定できる
    • ビジネス/マーケティング視点での指標取得に最適
  • 実装の優先度: ユーザー行動の分析が重視されるアプリでは高い

選択の基準

  1. アプリの現状:

    • アプリが不安定でクラッシュが頻繁に発生する場合 → Crashlyticsを優先
    • アプリの使用状況や行動パターンを理解したい場合 → Analyticsを優先
  2. 開発フェーズ:

    • 開発初期/ベータ版 → Crashlyticsを優先して安定性を確保
    • 安定稼働後の改善フェーズ → Analyticsを追加して利用状況を把握
  3. リソース制約:

    • 時間やリソースが限られている場合は、まずCrashlyticsを実装し、その後Analyticsを追加するアプローチが一般的

アプリの規模が小さく、Firebase FirestoreとAuthのみを利用している状況であれば、まずはCrashlyticsを実装して安定稼働を確保し、その後Analyticsを追加して利用状況の把握に進むという段階的なアプローチが合理的。

Discussion