コンソールへ移動

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

Firebase Crashlytics を動作させるためにユーザー側で行う設定はほとんどありません。SDK を追加するとすぐに、Crashlytics はクラッシュ レポートを Firebase コンソールに送信するようになります。

Firebase Crashlytics には、クラッシュ レポートを詳細に分析するために、カスタムキーカスタムログユーザー ID検出された例外という、設定が不要な 4 つのロギング メカニズムが用意されています。

カスタムキーを追加する

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

[CrashlyticsKit setObjectValue:forKey:] または関連するいずれかのメソッドで開始します。

- (void)setObjectValue:(id)value forKey:(NSString *)key;

// calls -description on value, perfect for NSStrings!
- (void)setIntValue:(int)value forKey:(NSString *)key;

- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;

- (void)setFloatValue:(float)value forKey:(NSString *)key;

場合によっては、既存の Key-Value の変更が必要です。その場合、次の例のように同じキーを、値を置き換えて呼び出します。

Objective-C
[CrashlyticsKit setIntValue:3 forKey:@"current_level"];
[CrashlyticsKit setObjectValue:@"logged_in" forKey:@"last_UI_action"];
Swift
Crashlytics.sharedInstance().setIntValue(42, forKey: "MeaningOfLife")
Crashlytics.sharedInstance().setObjectValue("Test value", forKey: "last_UI_action")

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

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

Objective-C

Objective-C では、CLS_LOG を使用すると問題の特定に役立ちます。これを使用すると、ログに関連付けられた Objective-C のクラス、メソッド、行番号に関する情報が自動的にログに組み込まれるようになります。

CLS_LOG の動作は、ロギング対象がビルドのデバッグまたはビルドのリリースのどちらであるかによって異なります。

  • デバッグビルド: CLS_LOGNSLog に渡されるため、出力を Xcode やデバイスまたはシミュレータで表示できます。
  • リリースビルド: パフォーマンスを向上させるために、CLS_LOG はその他すべての出力を無効にし、NSLog には出力を渡しません。

CLS_LOG でログを記録するには、次のように CLS_LOG(format, ...) を使用します。

CLS_LOG(@"Higgs-Boson detected! Bailing out... %@", attributesDict);

CLS_LOG の使用方法の詳細については、Crashlytics/Crashlytics.h ヘッダー ファイルをご覧ください。

Swift

Swift では、CLSLogv または CLSNSLogv が問題の特定に役立ちます。

CLSLogv および CLSNSLogv を使用してログを記録する際は、次の 2 点に注意してください。

  • 形式を指定する引数は、コンパイル時の定数文字列でなければなりません。これは Objective-C ではコンパイラによって強制されますが、現在のところ、この保護は Swift へのブリッジングで失われます。
  • ログの値を配列に格納し、その配列に対して getVaList を呼び出して値を取得します。

例:

func write(string: String) {
    CLSLogv("%@", getVaList([string]))
}
Swift 文字列を内挿しても、コンパイル時の定数文字列にはなりません。printf や NSLog の場合と同じく、CLSLog で非定数文字列を使用するとクラッシュが発生する可能性があります。

詳細

さらに細かく制御するには、CLSLog(format, ...)CLSNSLog(format, ...) を直接利用することができます。後者は NSLog に渡されるため、出力を Xcode や端末またはシミュレータで表示できます。CLSLog(format, ...)CLSNSLog(format, ...) はスレッドセーフです。CLSLog は、クラッシュを解決するうえで重要な情報をログに記録するためのものです。アプリ内イベントの追跡には使用しないでください。

ユーザー ID を設定する

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

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

Objective-C
[CrashlyticsKit setUserIdentifier:@"123456789"];
Swift
Crashlytics.sharedInstance().setUserIdentifier("123456789")

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

致命的でない例外をログに記録する

Crashlytics では自動的にアプリのクラッシュを報告するだけでなく、致命的でない例外をユーザーがログに記録できるようになっています。

iOS で非致命的な例外をログに記録するには、NSError オブジェクトを記録します。Crashlytics はこのオブジェクトを、クラッシュと同様に報告およびグループ化します。

Objective-C
[CrashlyticsKit recordError:error];
Swift
Crashlytics.sharedInstance().recordError(error)

recordError メソッドを使用する場合、NSError の構造と、このデータを使用して Crashlytics がどのようにクラッシュをグループ化するかを理解していることが重要です。recordError メソッドを誤った方法で使用すると、予測不可能な動作が発生し、アプリについてログに記録されたエラーの報告を Crashlytics が制限する必要が生じる可能性があります。

NSError オブジェクトの引数は次の 3 つです。domain: Stringcode: IntuserInfo: [AnyHashable : Any]? = nil

スタック トレース分析によってグループ化される致命的なクラッシュとは異なり、ログに記録されるエラーは NSError の domaincode を基準にグループ化されます。これは、致命的なクラッシュとログに記録されるエラーとの重要な違いです。たとえば、次のエラーをログに記録するとします。

NSDictionary *userInfo = @{
    NSLocalizedDescriptionKey: NSLocalizedString(@"The request failed.", nil),
    NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The response returned a 404.", nil),
    NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Does this page exist?", nil),
    ProductID: @"123456";
    UserID: @"Jane Smith"
};

NSError *error = [NSError domain:NSSomeErrorDomain
                          code:-1001
                          userInfo:userInfo];

これにより、NSSomeErrorDomain-1001 を基準にグループ化される新しい問題が作成されます。以降にログに記録される、同じドメインとコードの値が使用されているエラーは、この問題に分類されます。

ドメイン フィールドとコード フィールドには、ユーザー ID、プロダクト ID、タイムスタンプなどの一意の値を使用しないでください。これらのフィールドに一意の値を使用すると、問題のカーディナリティが高くなり、アプリ内でログに記録されたエラーの報告を Crashlytics が制限する必要が生じることがあります。一意の値は、代わりに userInfo 辞書オブジェクトに追加してください。

userInfo オブジェクト内に格納されたデータは Key-Value ペアに変換され、各問題内の keys/logs セクションに表示されます。

Crashlytics は所定のアプリ セッションで、最新の 8 件の例外だけを保管します。アプリが 1 つのセッションで 8 件を超える例外をスローすると、古い例外が失われます。

ログとカスタムキー

クラッシュ レポートと同様に、ログとカスタムキーを埋め込んで NSError にコンテキストを追加することができます。ただし、クラッシュに関連付けられるログと、ログに記録されるエラーに関連付けられるログには違いがあります。クラッシュが発生してアプリが再起動された時点で Crashlytics がディスクから取得するログは、クラッシュが発生する直前までに書き込まれたログです。NSError をログに記録した場合、アプリが直ちに終了することはありません。Crashlytics はアプリが次に起動されるまでログに記録されたエラーのレポートを送信せず、また、Crashlytics はディスク上でログに割り当てるスペースの量を制限しなければならないため、NSError が記録された後、十分な数のログが記録され、Crashlytics が端末からレポートを送信するときには、関連するすべてのログがローテーションされクリアされている可能性があります。アプリで NSErrors をログに記録し、CLSLog とカスタムキーを使用する場合は、このバランスに注意してください。

パフォーマンスに関する注意事項

NSError のロギングでは、コストがかなり高くなる場合があるので注意してください。Crashlytics を呼び出した時点で、Crashlytics はスタックの巻き戻しと呼ばれるプロセスによって現行スレッドのコールスタックをキャプチャします。このプロセスでは CPU と I/O の使用量が高まります。特に、DWARF 巻き戻しをサポートするアーキテクチャ(arm64 および x86)で顕著です。巻き戻しが完了した後、情報が同期的にディスクに書き込まれます。これにより、次の行でクラッシュが発生した場合のデータ損失を防ぎます。

この API 呼び出しはバックグラウンド スレッドで行っても差し支えありませんが、この呼び出しを別のキューにディスパッチすると、現在のスタック トレースのコンテキストが失われることに注意してください。

NSExceptions とは

Crashlytics には、NSException インスタンスを直接ロギング / 記録する機能がありません。一般に、Cocoa API と Cocoa Touch API は例外セーフではありません。つまり、@catch を使用すると、かなり慎重を期したとしても、プロセスに非常に深刻な想定外の副次作用がもたらされる可能性があります。コードでは決して @catch ステートメントを使用しないでください。このトピックについては、Apple のドキュメントをご覧ください。

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

デフォルトでは、Firebase Crashlytics は自動的にアプリの全ユーザーを対象にクラッシュ レポートを収集します。どのデータを送信するかをユーザーが細かく制御できるようにするには、デフォルトの代わりにオプトイン レポートを有効にします。

オプトイン レポートを有効にするには、自動収集を無効にして、オプトイン ユーザーに対してのみ Crashlytics を初期化する必要があります。

  1. Info.plist ファイルの新しいキーを使用して自動収集を無効にします。
    • キー: firebase_crashlytics_collection_enabled
    • 値: false
  2. Crashlytics を実行時に初期化して、選択されたユーザーに対して収集を有効にします。
    Objective-C
    [Fabric with:@[[Crashlytics class]]];
    Swift
    Fabric.with([Crashlytics.self])

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

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

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