במרכז הבקרה Crashlytics, אפשר ללחוץ על בעיה מסוימת ולקבל דוח מפורט על האירוע. אתם יכולים להתאים אישית את הדוחות האלה כדי להבין טוב יותר מה קורה באפליקציה ואת הנסיבות שקשורות לאירועים שמדווחים ל-Crashlytics.
מגדירים את האפליקציה כך שתתעד ביומן מפתחות בהתאמה אישית, הודעות ביומן בהתאמה אישית ומזהי משתמשים.
דיווח על חריגים אל Crashlytics.
קבלת יומני נתיב באופן אוטומטי אם האפליקציה משתמשת ב-Firebase SDK ל-Google Analytics. היומנים האלה מאפשרים לכם לראות את פעולות המשתמשים שהובילו לאירוע שנאסף על ידי Crashlytics באפליקציה שלכם.
משביתים את הדיווח האוטומטי על קריסות ומפעילים דיווח בהסכמה עבור המשתמשים. שימו לב שכברירת מחדל, Crashlytics אוסף באופן אוטומטי דוחות קריסה לגבי כל המשתמשים באפליקציה.
הוספת מפתחות בהתאמה אישית
מקשים בהתאמה אישית עוזרים לכם לקבל את המצב הספציפי של האפליקציה לפני הקריסה. אפשר לשייך צמדים שרירותיים של מפתח/ערך לדוחות הקריסה, ואז להשתמש במפתחות המותאמים אישית כדי לחפש ולסנן דוחות קריסה במסוף Firebase.
- במרכז הבקרה של Crashlytics, אפשר לחפש בעיות שתואמות למפתח מותאם אישית.
- כשבודקים בעיה ספציפית במסוף, אפשר לראות את המפתחות המותאמים אישית שמשויכים לכל אירוע (כרטיסיית המשנה מפתחות), ואפילו לסנן את האירועים לפי מפתחות מותאמים אישית (התפריט מסנן בחלק העליון של הדף).
משתמשים בשיטה setCustomValue
כדי להגדיר צמדי מפתח/ערך. לדוגמה:
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
כשמגדירים מספרים שלמים, ערכים בוליאניים או מספרים עשרוניים, צריך להוסיף את הערך בתוך סוגריים מרובעים @(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"];
אפשר גם לשנות את הערך של מפתח קיים על ידי קריאה למפתח והגדרת ערך אחר. לדוגמה:
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"];
כדי להוסיף צמדי מפתח/ערך בכמות גדולה, משתמשים בשיטה setCustomKeysAndValues
עם NSDictionary כפרמטר היחיד:
Swift
let keysAndValues = [ "string key" : "string value", "string key 2" : "string value 2", "boolean key" : true, "boolean key 2" : false, "float key" : 1.01, "float key 2" : 2.02 ] as [String : Any] Crashlytics.crashlytics().setCustomKeysAndValues(keysAndValues)
Objective-C
NSDictionary *keysAndValues = @{@"string key" : @"string value", @"string key 2" : @"string value 2", @"boolean key" : @(YES), @"boolean key 2" : @(NO), @"float key" : @(1.01), @"float key 2" : @(2.02)}; [[FIRCrashlytics crashlytics] setCustomKeysAndValues: keysAndValues];
הוספה של הודעות מותאמות אישית ביומן
כדי לקבל יותר הקשר לגבי האירועים שהובילו לקריסה, אתם יכולים להוסיף לאפליקציה יומנים מותאמים אישית של Crashlytics. Crashlytics משייך את היומנים לנתוני הקריסה ומציג אותם בדף Crashlytics של Firebase Console, בכרטיסייה Logs.
Swift
אפשר להשתמש ב-log()
או ב-log(format:, arguments:)
כדי לזהות בעיות. אם רוצים לקבל פלט יומן שימושי עם הודעות, האובייקט שמעבירים אל log()
צריך להיות תואם למאפיין CustomStringConvertible
. log()
מחזירה את מאפיין התיאור שהגדרתם לאובייקט. לדוגמה:
Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")
.log(format:, arguments:)
מעצב את הערכים שמוחזרים מהקריאה ל-getVaList()
. לדוגמה:
Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))
למידע נוסף על השימוש ב-log()
או ב-log(format:, arguments:)
, אפשר לעיין בCrashlytics
מסמכי העזרה.
Objective-C
אפשר להשתמש ב-log
או ב-logWithFormat
כדי לזהות בעיות. שימו לב: אם רוצים לקבל פלט שימושי של יומן עם הודעות, האובייקט שמעבירים לאחת מהשיטות צריך לבטל את מאפיין המופע description
.
לדוגמה:
[[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];
לפרטים נוספים על השימוש ב-log
וב-logWithFormat
, אפשר לעיין במסמכי העזרה של Crashlytics.
הגדרת מזהי משתמשים
כדי לאבחן בעיה, לעיתים קרובות מועיל לדעת אילו מהמשתמשים נתקלו בקריסה מסוימת. Crashlytics כולל דרך לזיהוי משתמשים באופן אנונימי בדוחות הקריסות.
כדי להוסיף מזהי משתמשים לדוחות, צריך להקצות לכל משתמש מזהה ייחודי בצורה של מספר מזהה, אסימון או ערך גיבוב:
Swift
Crashlytics.crashlytics().setUserID("123456789")
Objective-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];
אם תצטרכו אי פעם לנקות מזהה משתמש אחרי שהגדרתם אותו, תצטרכו לאפס את הערך למחרוזת ריקה. ניקוי מזהה משתמש לא מסיר רשומות קיימות של Crashlytics. אם אתם צריכים למחוק רשומות שמשויכות למזהה משתמש, פנו לתמיכה של Firebase.
דיווח על חריגות לא קריטיות
בנוסף לדיווח אוטומטי על קריסות של האפליקציה, Crashlytics מאפשרת לכם לתעד חריגים לא קריטיים ולשלוח אותם אליכם בפעם הבאה שהאפליקציה תופעל.
אפשר להקליט חריגים לא קריטיים על ידי הקלטת אובייקטים מסוג NSError
באמצעות השיטה recordError
. recordError
מתעד את מחסנית הקריאות של השרשור על ידי קריאה ל-[NSThread callStackReturnAddresses]
.
Swift
Crashlytics.crashlytics().record(error: error)
Objective-C
[[FIRCrashlytics crashlytics] recordError:error];
כשמשתמשים בשיטה recordError
, חשוב להבין את המבנה ואיך Crashlytics משתמש בנתונים כדי לקבץ קריסות.NSError
שימוש לא נכון בשיטה recordError
עלול לגרום להתנהגות בלתי צפויה, וגם לגרום ל-Crashlytics להגביל את הדיווח על שגיאות שנרשמו באפליקציה.
לאובייקט NSError
יש שלושה ארגומנטים:
domain: String
code: Int
userInfo: [AnyHashable : Any]? = nil
שלא כמו קריסות חמורות שמקובצות באמצעות ניתוח של דוח קריסות, שגיאות שנרשמות ביומן מקובצות לפי domain
ו-code
. חשוב להבחין בין קריסות קטלניות לבין שגיאות שנרשמות ביומן. לדוגמה:
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];
כשמתעדים את השגיאה שלמעלה, נוצרת בעיה חדשה שמקובצת לפי NSSomeErrorDomain
ו--1001
. שגיאות נוספות שנרשמות ביומן ומשתמשות באותם ערכים של תחום וקוד מקובצות תחת אותה בעיה. הנתונים שכלולים באובייקט userInfo
מומרים לצמדי מפתח/ערך ומוצגים בקטע keys/logs בתוך בעיה ספציפית.
יומנים ומפתחות בהתאמה אישית
בדומה לדוחות קריסה, אפשר להטמיע יומנים ומפתחות בהתאמה אישית כדי להוסיף הקשר לNSError
. עם זאת, יש הבדל בין היומנים שמצורפים לקריסות לבין היומנים של שגיאות שנרשמות. כשמתרחש קריסה והאפליקציה מופעלת מחדש, היומנים Crashlytics שאוחזרו מהדיסק הם אלה שנכתבו עד לזמן הקריסה. כשמתעדים NSError
, האפליקציה לא מסיימת את הפעולה באופן מיידי. Crashlytics שולח את דוח השגיאות שנרשם רק בהפעלה הבאה של האפליקציה, והוא צריך להגביל את כמות המקום שמוקצה ליומנים בדיסק. לכן, יכול להיות שיירשמו מספיק יומנים אחרי ש-NSError
מתועד, כך שכל היומנים הרלוונטיים יוחלפו עד ש-Crashlytics ישלח את הדוח מהמכשיר. חשוב לזכור את האיזון הזה כשמתחברים ל-NSErrors
ומשתמשים ביומנים ובמפתחות מותאמים אישית באפליקציה.
שיקולי ביצועים
חשוב לזכור שרישום של NSError
ביומן יכול להיות יקר למדי. בזמן שאתם מבצעים את השיחה, Crashlytics מצלם את ערימת הקריאות של השרשור הנוכחי באמצעות תהליך שנקרא 'ביטול הערימה'. התהליך הזה יכול להיות אינטנסיבי מבחינת מעבד וקלט/פלט, במיוחד בארכיטקטורות שתומכות בביטול של DWARF (arm64 ו-x86).
אחרי שהביטול מסתיים, המידע נכתב לדיסק באופן סינכרוני.
כך אפשר למנוע אובדן נתונים אם השורה הבאה תקרוס.
אפשר לשלוח קריאה ל-API הזה בשרשור ברקע, אבל צריך לזכור שאם מעבירים את הקריאה הזו לתור אחר, ההקשר של מעקב המחסנית הנוכחי אובד.
מה לגבי NSExceptions?
Crashlytics לא מציעה מתקן לרישום ולתיעוד של מקרים של NSException
ישירות. באופן כללי, ממשקי ה-API של Cocoa ו-Cocoa Touch לא בטוחים מפני חריגים. כלומר, השימוש ב-@catch
עלול לגרום לתופעות לוואי חמורות ולא מכוונות בתהליך, גם כשמשתמשים בו בזהירות רבה. אסור להשתמש בהצהרות @catch
בקוד. אפשר לעיין במסמכי התיעוד של Apple בנושא.
התאמה אישית של עקבות מחסנית
אם האפליקציה פועלת בסביבה לא מקורית (כמו C++ או Unity), אפשר להשתמש ב-Exception Model API כדי לדווח על מטא-נתונים של קריסות בפורמט החריגים המקורי של האפליקציה. חריגים שדווחו מסומנים כחריגים לא קריטיים.
Swift
var ex = ExceptionModel(name:"FooException", reason:"There was a foo.") ex.stackTrace = [ StackFrame(symbol:"makeError", file:"handler.js", line:495), StackFrame(symbol:"then", file:"routes.js", line:102), StackFrame(symbol:"main", file:"app.js", line:12), ] crashlytics.record(exceptionModel:ex)
Objective-C
FIRExceptionModel *model = [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."]; model.stackTrace = @[ [FIRStackFrame stackFrameWithSymbol:@"makeError" file:@"handler.js" line:495], [FIRStackFrame stackFrameWithSymbol:@"then" file:@"routes.js" line:102], [FIRStackFrame stackFrameWithSymbol:@"main" file:@"app.js" line:12], ]; [[FIRCrashlytics crashlytics] recordExceptionModel:model];
אפשר גם לאתחל מסגרות מחסנית בהתאמה אישית רק עם כתובות:
Swift
var ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.") ex.stackTrace = [ StackFrame(address:0xfa12123), StackFrame(address:12412412), StackFrame(address:194129124), ] crashlytics.record(exceptionModel:ex)
Objective-C
FIRExceptionModel *model = [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."]; model.stackTrace = @[ [FIRStackFrame stackFrameWithAddress:0xfa12123], [FIRStackFrame stackFrameWithAddress:12412412], [FIRStackFrame stackFrameWithAddress:194129124], ]; [[FIRCrashlytics crashlytics] recordExceptionModel:model];
אחזור יומנים של נתיבי ניווט
יומני נתוני נתיב (breadcrumb) מאפשרים לכם להבין טוב יותר את האינטראקציות שהיו למשתמש עם האפליקציה לפני קריסה, אירוע לא קטלני או אירוע ANR. היומנים האלה יכולים לעזור כשמנסים לשחזר בעיה ולנפות באגים.
היומנים של נתיבי הניווט מבוססים על Google Analytics, ולכן כדי לקבל אותם צריך להפעיל את Google Analytics בפרויקט Firebase ולהוסיף את Firebase SDK ל-Google Analytics לאפליקציה. אחרי שממלאים את הדרישות האלה, היומנים של נתיבי הניווט נכללים אוטומטית בנתוני האירוע בכרטיסייה יומנים כשמציגים את פרטי הבעיה.
Analytics SDK
מתעד באופן אוטומטי את האירוע screen_view
מה שמאפשר להציג ביומני ה-breadcrumb רשימה של מסכים שנצפו לפני הקריסה, האירוע הלא קטלני או האירוע מסוג ANR. יומן של נתיב ניווט מכיל פרמטר firebase_screen_class
.screen_view
יומני נתיב הניווט כוללים גם אירועים מותאמים אישית שאתם מתעדים באופן ידני במהלך הסשן של המשתמש, כולל נתוני הפרמטרים של האירוע. הנתונים האלה יכולים לעזור להציג סדרה של פעולות משתמש שהובילו לקריסה, לאירוע לא קטלני או לאירוע ANR.
חשוב לדעת שאפשר לשלוט באיסוף ובשימוש בנתוני Google Analytics, כולל הנתונים שמאכלסים את יומני הנתיבים.
הפעלת דיווח על הסכמה
כברירת מחדל, Crashlytics אוסף באופן אוטומטי דוחות קריסה לגבי כל המשתמשים באפליקציה. כדי לתת למשתמשים יותר שליטה על הנתונים שהם שולחים, אתם יכולים להפעיל דיווח בהסכמה. לשם כך, צריך להשבית את הדיווח האוטומטי ולשלוח נתונים אל Crashlytics רק כשאתם בוחרים לעשות זאת בקוד.
כדי להשבית את האיסוף האוטומטי, מוסיפים מפתח חדש לקובץ
Info.plist
:- מקש:
FirebaseCrashlyticsCollectionEnabled
- ערך:
false
- מקש:
מפעילים את האיסוף עבור משתמשים נבחרים על ידי קריאה ל-Crashlytics data collection override בזמן הריצה. ערך ההחלפה נשמר בכל ההפעלות הבאות של האפליקציה, כך ש-Crashlytics יכול לאסוף באופן אוטומטי דוחות עבור המשתמש הזה.
Swift
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Objective-C
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
אם המשתמש יבחר בהמשך להפסיק את איסוף הנתונים, תוכלו להעביר את הערך
false
כערך ברירת המחדל. הערך הזה יחול בפעם הבאה שהמשתמש יפעיל את האפליקציה, וימשיך לחול בכל ההפעלות הבאות של האפליקציה על ידי אותו משתמש.
ניהול נתונים של תובנות לגבי קריסות
התובנות לגבי קריסות עוזרות לכם לפתור בעיות על ידי השוואה בין עקבות מחסנית (stack traces) אנונימיים שלכם לבין עקבות מאפליקציות אחרות ב-Firebase, ומודיעות לכם אם הבעיה שלכם היא חלק ממגמה רחבה יותר. במקרים רבים, Crash Insights מספק גם מקורות מידע שיעזרו לכם לנפות באגים בקריסה.
התכונה 'תובנות לגבי קריסות' משתמשת בנתוני קריסות מצטברים כדי לזהות מגמות נפוצות של יציבות. אם אתם לא רוצים לשתף את נתוני האפליקציה, אתם יכולים לבטל את ההסכמה לשיתוף נתונים ב-Crash Insights. כדי לעשות זאת, פותחים את התפריט Crash Insights בחלק העליון של רשימת הבעיות Crashlytics ב-Firebase Console.