בלוח הבקרה Crashlytics, אפשר ללחוץ על בעיה כדי לקבל דוח אירועים מפורט. אתם יכולים להתאים אישית את הדוחות האלה כדי לעזור לכם להבין טוב יותר מה קורה באפליקציה ואת הנסיבות של האירועים שדווחו ל-Crashlytics.
מוסיפים לאפליקציה כלים לתיעוד ביומן של מפתחות בהתאמה אישית, הודעות יומן בהתאמה אישית ומזהי משתמשים.
מדווחים על חריגים אל Crashlytics.
לקבל באופן אוטומטי יומני נתיב ניווט אם האפליקציה שלכם משתמשת ב-Firebase SDK ל-Google Analytics. היומנים האלה מאפשרים לכם לראות את הפעולות של המשתמשים שהובילו לאירוע שנאסף על ידי Crashlytics באפליקציה.
משביתים את הדיווח האוטומטי על קריסות ומפעילים דיווח על בסיס הסכמה למשתמשים. חשוב לזכור ש-Crashlytics אוסף באופן אוטומטי דוחות קריסה מכל המשתמשים באפליקציה.
הוספת מפתחות בהתאמה אישית
מפתחות בהתאמה אישית עוזרים לכם לקבל את המצב הספציפי של האפליקציה לפני קריסה. אתם יכולים לשייך צמדי מפתח/ערך שרירותיים לדוחות הקריסה, ואז להשתמש במפתחות המותאמים אישית כדי לחפש ולסנן דוחות קריסה במסוף Firebase.
- במרכז הבקרה Crashlytics אפשר לחפש בעיות שתואמות למפתח מותאם אישית.
- כשבודקים בעיה ספציפית במסוף, אפשר לראות את המפתחות המותאמים אישית המשויכים לכל אירוע (כרטיסיית המשנה Keys) ואפילו לסנן את האירועים לפי מפתחות מותאמים אישית (תפריט Filter בחלק העליון של הדף).
משתמשים ב-method 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, בכרטיסייה יומנים.
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
, חשוב להבין את המבנה של NSError
ואת האופן שבו Crashlytics משתמש בנתונים כדי לקבץ תאונות. שימוש שגוי בשיטה 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 מתעד את סטאק הקריאות של השרשור הנוכחי באמצעות תהליך שנקרא ביטול סטאק. התהליך הזה יכול להיות מוגזם מבחינת מעבדים (CPU) ומבחינת קלט/פלט (I/O), במיוחד בארכיטקטורות שתומכות בביטול חבילות DWARF (arm64 ו-x86).
בסיום הביטול, המידע נכתב בדיסק באופן סינכרוני.
כך אפשר למנוע אובדן נתונים אם השורה הבאה תקרוס.
אפשר לבצע קריאה ל-API הזה בבטחה בשרשור רקע, אבל חשוב לזכור שהעברת הקריאה הזו לתור אחר גורמת לאובדן ההקשר של מעקב הסטאק הנוכחי.
מה לגבי NSExceptions?
ב-Crashlytics אין אפשרות לתעד ישירות ביומן את המופעים של NSException
. באופן כללי, ממשקי ה-API של Cocoa ו-Cocoa Touch לא מוגנים מפני חריגות. כלומר, לשימוש ב-@catch
יכולות להיות תופעות לוואי לא רצויות חמורות מאוד בתהליך, גם אם משתמשים בו בזהירות רבה. לעולם אל תשתמשו בהצהרות @catch
בקוד. אפשר לעיין במסמכי התיעוד של Apple בנושא.
התאמה אישית של מעקב נתונים ב-stack
אם האפליקציה פועלת בסביבה לא ילידית (כמו 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];
אחזור יומני נתיבי ניווט
יומני נתיב הניווט עוזרים לכם להבין טוב יותר את האינטראקציות של משתמש עם האפליקציה שלכם עד לתאונה, לאירוע לא קטלני או לאירוע ANR. היומנים האלה יכולים להיות מועילים כשמנסים לשחזר בעיה ולנפות באגים בה.
יומני הלחם מופעל על ידי Google Analytics, ולכן כדי לקבל יומני לחם צריך להפעיל את Google Analytics בפרויקט Firebase ולהוסיף את ה-Firebase SDK ל-Google Analytics באפליקציה. אחרי שתבצעו את הדרישות האלה, יומני הלחם ייכללו באופן אוטומטי בנתונים של אירוע בכרטיסייה יומנים כשמציגים את פרטי הבעיה.
ערכת ה-SDK של Analytics רושמת באופן אוטומטי את האירוע screen_view
, וכך מאפשרת ליומנים של נתיב הניווט להציג רשימה של המסכים שנצפו לפני האירוע של קריסה, אירוע לא קטלני או אירוע ANR. יומן של נתיב breadcrumbs מסוג screen_view
מכיל פרמטר firebase_screen_class
.
יומני נתיב הניווט מאוכלסים גם באירועים מותאמים אישית שרשמתם באופן ידני במהלך הסשן של המשתמש, כולל נתוני הפרמטרים של האירוע. הנתונים האלה יכולים לעזור להציג סדרה של פעולות משתמש שהובילו לתאונה, לאירוע ANR או לאירוע לא קטלני.
לתשומת ליבכם: אתם יכולים לשלוט באיסוף ובשימוש בנתוני Google Analytics, כולל הנתונים שמאכלסים את יומני הלחם.
הפעלת דיווח על הסכמה
כברירת מחדל, Crashlytics אוסף באופן אוטומטי דוחות קריסה של כל המשתמשים באפליקציה. כדי לתת למשתמשים שליטה רבה יותר על הנתונים שהם שולחים, אפשר להפעיל דיווח על הסכמה מפורשת על ידי השבתת הדיווח האוטומטי ושליחת נתונים אל Crashlytics רק כשבוחרים בכך בקוד:
כדי להשבית את האיסוף האוטומטי, מוסיפים מפתח חדש לקובץ
Info.plist
:- מקש:
FirebaseCrashlyticsCollectionEnabled
- ערך:
false
- מקש:
כדי להפעיל את האיסוף למשתמשים נבחרים, צריך להפעיל את ההחרגה של איסוף הנתונים Crashlytics בזמן הריצה. ערך ההחרגה נשמר בכל ההפעלות של האפליקציה, כדי ש-Crashlytics יוכל לאסוף דוחות באופן אוטומטי.
כדי לבטל את ההסכמה לדיווח אוטומטי על קריסות, מעבירים את הערך
false
כערך לשינוי מברירת המחדל. כשהערך מוגדר ל-false
, הערך החדש לא יחול עד להפעלה הבאה של האפליקציה.Swift
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Objective-C
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
ניהול הנתונים של תובנות לגבי קריסות
התכונה Crash Insights עוזרת לכם לפתור בעיות על ידי השוואה של נתוני המעקב אחרי סטאק (stack trace) שהוסרו מהם פרטי הזיהוי לנתוני מעקב מאפליקציות אחרות ב-Firebase, ומציינת אם הבעיה היא חלק ממגמה רחבה יותר. לגבי בעיות רבות, התכונה 'תובנות לגבי קריסות' מספקת גם מקורות מידע שיעזרו לכם לנפות את הבאגים שגרמו לקריסה.
התכונה 'תובנות לגבי קריסות' משתמשת בנתוני קריסות שנצברו כדי לזהות מגמות נפוצות ביציבות. אם אתם מעדיפים לא לשתף את נתוני האפליקציה, תוכלו לבטל את ההסכמה לשימוש בתכונה 'תובנות לגבי קריסות' בתפריט תובנות לגבי קריסות בחלק העליון של רשימת הבעיות Crashlytics במסוף Firebase.