Menyesuaikan laporan error Firebase Crashlytics

Panduan ini berisi penjelasan cara menyesuaikan laporan error menggunakan Firebase Crashlytics SDK. Secara default, Crashlytics mengumpulkan laporan error secara otomatis untuk semua pengguna aplikasi Anda (Anda dapat menonaktifkan pelaporan error otomatis dan mengaktifkan pilihan keikutsertaan pelaporan untuk pengguna Anda). Crashlytics menyediakan empat mekanisme logging siap pakai: kunci kustom, log kustom, ID pengguna, dan pengecualian yang tertangkap.

Menambahkan kunci kustom

Kunci kustom membantu Anda mendapatkan status spesifik aplikasi sebelum terjadinya error. Anda dapat mengaitkan key-value pair apa saja dengan laporan error, dan melihatnya di Firebase console.

Gunakan metode setCustomValue untuk menetapkan key-value pair. Contoh:

Swift

// Set int_key to 100.
Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")

// Set str_key to "hello".
Crashlytics.crashlytics().setCustomValue("hello", forKey: "str_key")

Objective-C

Saat menetapkan integer, boolean, atau float, kotakkan nilai sebagai @(value).

// Set int_key to 100.
[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];

// Set str_key to "hello".
[[FIRCrashlytics crashlytics] setCustomValue:@"hello" forKey:@"str_key"];

Anda juga dapat mengubah nilai kunci yang ada dengan memanggil kunci tersebut dan menetapkannya ke nilai yang berbeda. Contoh:

Swift

Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")

// Set int_key to 50 from 100.
Crashlytics.crashlytics().setCustomValue(50, forKey: "int_key")

Objective-C

[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];

// Set int_key to 50 from 100.
[[FIRCrashlytics crashlytics] setCustomValue:@(50) forKey:@"int_key"];

Menambahkan pesan log kustom

Untuk memberikan lebih banyak konteks pada peristiwa yang menyebabkan error, Anda dapat menambahkan log Crashlytics kustom ke aplikasi Anda. Crashlytics mengaitkan log dengan data error dan menampilkannya di halaman Crashlytics dari Firebase console, pada tab Log.

Swift

Gunakan log() atau log(format:, arguments:) untuk membantu menentukan masalah. Jika Anda ingin mendapatkan output log yang berguna dengan pesan, objek yang Anda teruskan ke log() harus sesuai dengan properti CustomStringConvertible. log() menampilkan properti deskripsi yang Anda tentukan untuk objek. Contoh:

Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")

.log(format:, arguments:) memformat nilai yang ditampilkan setelah memanggil getVaList(). Contoh:

Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))

Untuk detail selengkapnya cara menggunakan log() atau log(format:, arguments:), lihat dokumentasi referensi fungsi Crashlytics.

Objective-C

Gunakan log atau logWithFormat untuk membantu menentukan masalah. Perhatikan bahwa jika Anda ingin mendapatkan output log dengan pesan yang jelas, objek yang Anda teruskan ke salah satu metode tersebut harus mengganti properti instance description. Contoh:

[[FIRCrashlytics crashlytics] log:@"Simple string message"];

[[FIRCrashlytics crashlytics] logWithFormat:@"Higgs-Boson detected! Bailing out... %@", attributesDict];

[[FIRCrashlytics crashlytics] logWithFormat:@"Logging a variable argument list %@" arguments:va_list_arg];

Untuk detail selengkapnya cara menggunakan log dan logWithFormat, lihat dokumentasi referensi fungsi Crashlytics.

Menetapkan ID pengguna

Untuk mendiagnosis masalah, mengetahui pengguna mana yang mengalami error akan sangat membantu. Crashlytics menyertakan cara mengidentifikasi pengguna secara anonim dalam laporan error Anda.

Untuk menambahkan ID pengguna ke laporan, tetapkan pengenal unik untuk masing-masing pengguna dalam bentuk nomor ID, token, atau nilai hash:

Swift
Crashlytics.crashlytics().setUserID("123456789")
Objective-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];

Jika Anda perlu menghapus ID pengguna setelah menyetelnya, setel ulang nilai ke string kosong. Menghapus ID pengguna tidak menghapus data Crashlytics yang ada. Jika ingin menghapus data yang terkait dengan ID pengguna tertentu, hubungi dukungan Firebase.

Melaporkan pengecualian non-fatal

Selain melaporkan error aplikasi secara otomatis, Crashlytics memungkinkan Anda mencatat pengecualian non-fatal dan mengirimkannya kepada Anda saat berikutnya aplikasi diluncurkan.

Anda dapat merekam pengecualian non-fatal dengan merekam objek NSError dengan metode recordError. recordError merekam stack panggilan thread dengan memanggil [NSThread callStackReturnAddresses].

Swift

Crashlytics.crashlytics().record(error: error)

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

Saat menggunakan metode recordError, penting untuk memahami struktur NSError dan cara Crashlytics menggunakan data untuk mengelompokkan error. Penggunaan metode recordError yang salah dapat menyebabkan perilaku yang tidak dapat diprediksi dan dapat menyebabkan Crashlytics membatasi pelaporan error yang dicatat ke dalam log untuk aplikasi Anda.

Objek NSError memiliki tiga argumen:

  • domain: String
  • code: Int
  • userInfo: [AnyHashable : Any]? = nil

Tidak seperti error fatal yang dikelompokkan melalui analisis pelacakan tumpukan, error yang dicatat dikelompokkan berdasarkan domain dan code. Ini adalah perbedaan penting antara error fatal dan error yang dicatat. Contoh:

Swift

let userInfo = [
  NSLocalizedDescriptionKey: NSLocalizedString("The request failed.", comment: ""),
  NSLocalizedFailureReasonErrorKey: NSLocalizedString("The response returned a 404.", comment: ""),
  NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Does this page exist?", comment: ""),
  "ProductID": "123456",
  "View": "MainView"
]

let error = NSError.init(domain: NSCocoaErrorDomain,
                         code: -1001,
                         userInfo: userInfo)

Objective-C

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",
  @"View": @"MainView",
};

NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
                                     code:-1001
                                 userInfo:userInfo];

Saat Anda mencatat error di atas, error baru akan dikelompokkan berdasarkan NSSomeErrorDomain dan -1001. Error lainnya yang dicatat yang menggunakan domain dan nilai kode yang sama dikelompokkan dalam masalah yang sama. Data yang terdapat dalam objek userInfo dikonversi menjadi key-value pair dan ditampilkan di kolom key/log dalam satu masalah.

Peringatan: Hindari menggunakan nilai unik, seperti ID pengguna, ID produk, dan stempel waktu di kolom kode dan domain. Menggunakan nilai unik di kolom ini menyebabkan kardinalitas masalah yang tinggi dan dapat menyebabkan Crashlytics perlu membatasi pelaporan error yang dicatat di aplikasi Anda. Sebaliknya, nilai unik harus ditambahkan ke objek kamus userInfo.

Pencatatan log dan kunci kustom

Sama seperti laporan error, Anda dapat menyematkan log dan kunci kustom untuk menambahkan konteks ke NSError. Namun, ada perbedaan antara log mana yang dilampirkan pada error dengan error yang dicatat. Saat terjadi error lalu aplikasi diluncurkan kembali, log yang diambil Crashlytics dari disk adalah log yang ditulis hingga saat error terjadi. Saat Anda mencatat NSError, aplikasi tidak segera dihentikan. Karena Crashlytics hanya mengirimkan laporan error yang dicatat pada peluncuran aplikasi berikutnya, tapi juga harus membatasi jumlah ruang yang dialokasikan untuk log pada disk, ada kemungkinan log terus dibuat setelah NSError dicatat, sehingga semua log yang relevan dirotasi keluar pada saat Crashlytics mengirimkan laporan dari perangkat. Ingatlah keseimbangan ini saat mencatat log NSErrors dan menggunakan log serta kunci kustom di aplikasi Anda.

Pertimbangan performa

Perlu diingat bahwa pencatatan log NSError bisa jadi cukup mahal. Pada saat Anda melakukan panggilan, Crashlytics menangkap stack panggilan thread saat ini dengan menggunakan proses yang disebut pelepasan stack (stack unwinding). Proses ini memerlukan CPU dan I/O secara intensif, terutama pada arsitektur yang mendukung pelepasan DWARF (arm64 dan x86). Setelah proses pelepasan selesai, informasinya ditulis ke disk secara sinkron. Ini untuk mencegah hilangnya data jika baris berikutnya mengalami error.

Meskipun aman untuk memanggil API ini di thread latar belakang, ingat bahwa mengirimkan panggilan ini ke antrean lainnya akan menghilangkan konteks pelacakan tumpukan saat ini.

Bagaimana dengan NSExceptions?

Crashlytics tidak menawarkan fasilitas untuk membuat log dan merekam instance NSException secara langsung. Secara umum, API Cocoa and Cocoa Touch tidak benar-benar aman dari pengecualian. Itu berarti penggunaan @catch dapat memiliki efek samping sangat serius yang tidak diinginkan dalam proses Anda, bahkan jika digunakan dengan sangat hati-hati. Jangan pernah menggunakan pernyataan @catch dalam kode Anda. Lihat dokumentasi Apple untuk topik ini.

Menyesuaikan pelacakan tumpukan

Jika aplikasi Anda berjalan di lingkungan non-native (seperti C ++ atau Unity), Anda dapat menggunakan API Exception Model untuk melaporkan metadata error dalam format pengecualian native aplikasi. Pengecualian yang dilaporkan ditandai sebagai non-fatal.

Swift

var  ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.")
ex.stackTrace = [
  StackFrame.init(symbol:"makeError" fileName:"handler.js" lineNumber:495),
  StackFrame.init(symbol:"then" fileName:"routes.js" lineNumber:102),
  StackFrame.init(symbol:"main" fileName:"app.js" lineNumber:12),
]

crashlytics.record(exceptionModel:ex)

Objective-C

FIRExceptionModel *model =
    [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
model.stackTrace = @[
  [FIRStackFrame stackFrameWithSymbol:@"makeError" fileName:@"handler.js" lineNumber:495],
  [FIRStackFrame stackFrameWithSymbol:@"then" fileName:@"routes.js" lineNumber:102],
  [FIRStackFrame stackFrameWithSymbol:@"main" fileName:@"app.js" lineNumber:12],
];

Mengaktifkan pilihan keikutsertaan pelaporan

Secara default, Crashlytics mengumpulkan laporan error secara otomatis untuk semua pengguna aplikasi Anda. Untuk memberikan lebih banyak kontrol kepada pengguna atas data yang mereka kirim, Anda dapat mengaktifkan pilihan keikutsertaan pelaporan untuk pengguna dengan menonaktifkan pengumpulan otomatis dan menginisialisasi Crashlytics hanya untuk pengguna yang dipilih:

  1. Nonaktifkan pengumpulan otomatis dengan menambahkan kunci baru ke file Info.plist Anda:

    • Kunci: FirebaseCrashlyticsCollectionEnabled
    • Nilai: false
  2. Aktifkan pengumpulan untuk pengguna tertentu dengan memanggil penggantian pengumpulan data Crashlytics saat runtime. Nilai penggantian dipertahankan setiap kali aplikasi Anda diluncurkan, sehingga Crashlytics dapat mengumpulkan laporan secara otomatis. Untuk tidak diikutsertakan dalam pelaporan error otomatis, teruskan false sebagai nilai pengganti. Jika ditetapkan ke false, nilai baru tidak berlaku hingga kali berikutnya aplikasi dijalankan.

    Swift
    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
    Objective-C
    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Mengelola data Crash Insights

Crash Insights membantu Anda mengatasi masalah dengan membandingkan pelacakan tumpukan anonim dengan pelacakan dari aplikasi Firebase lain, serta memberitahukan apakah masalah Anda adalah bagian dari tren yang lebih besar. Untuk banyak masalah, Crash Insights bahkan menyediakan resource untuk membantu Anda men-debug error.

Crash Insights menggunakan data error agregat untuk mengidentifikasi tren stabilitas umum. Jika tidak ingin membagikan data aplikasi, Anda dapat menonaktifkan Crash Insights dari menu Crash Insights di bagian atas daftar masalah Crashlytics pada Firebase console.