התאמה אישית של דוחות הקריסה ב-Firebase Crashlytics


בלוח הבקרה של Crashlytics אפשר ללחוץ על בעיה ולקבל דוח אירועים. אתם יכולים להתאים אישית את הדוחות האלה כדי לעזור לכם להבין טוב יותר מה קורה באפליקציה ואת הנסיבות של האירועים שדווחו ל-Crashlytics.

  • לקבל באופן אוטומטי יומני נתיב ניווט אם האפליקציה שלכם משתמשת ב-Firebase SDK ל-Google Analytics. היומנים האלה מאפשרים לכם לראות פעולות של המשתמשים שהובילו לאירוע שנאסף Crashlytics באפליקציה.

  • ולכבות את הדיווח האוטומטי על קריסות להפעיל דיווח על הבעת הסכמה עבור המשתמשים. שימו לב, על ידי כברירת מחדל, Crashlytics אוסף דוחות קריסה באופן אוטומטי משתמשי האפליקציה.

הוספת מפתחות בהתאמה אישית

מפתחות בהתאמה אישית עוזרים לכם לקבל את המצב הספציפי של האפליקציה לפני קריסת האפליקציה. אתם יכולים לשייך צמדי מפתח/ערך שרירותיים לדוחות הקריסה, ואז להשתמש במפתחות המותאמים אישית כדי לחפש ולסנן דוחות קריסה במסוף Firebase.

  • במרכז הבקרה Crashlytics אפשר לחפש בעיות שתואמות למפתח מותאם אישית.
  • כשבודקים בעיה ספציפית במסוף, אפשר לראות מפתחות מותאמים אישית שמשויכים לכל אירוע (כרטיסיית המשנה מפתחות) ואפילו לסנן את אירועים לפי מפתחות מותאמים אישית (תפריט סינון שבחלק העליון של הדף).

משתמשים ב-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 בנושא.

התאמה אישית של דוחות הקריסות

אם האפליקציה פועלת בסביבה לא מותאמת (כמו C++ או Unity), תוכלו להשתמש ממשק ה-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 for Google Analytics לאפליקציה. לאחר העמידה בדרישות האלה, יומני המיקומים באתר מתועדים באופן אוטומטי כלול בנתוני אירוע בכרטיסייה יומנים כאשר מציגים את הפרטים של בעיה.

ערכת ה-SDK Analytics האירוע screen_view מתעד באופן אוטומטי שמאפשר ליומני המיקומים להציג רשימה של מסכים שהוצגו לפני קריסה, אירוע לא חמור או אירוע ANR. יומן נתיבי ניווט screen_view מכיל firebase_screen_class.

יומני נתיב הניווט מאוכלסים גם באירועים מותאמים אישית שתתעדו באופן ידני במהלך הסשן של המשתמש, כולל נתוני הפרמטרים של האירוע. הנתונים האלה יכולים לעזור להציג סדרה של פעולות משתמש שהובילו לתאונה, לאירוע ANR או לאירוע לא קטלני.

לתשומת ליבך: אפשר לשלוט באיסוף של נתוני Google Analytics ובשימוש בהם, שכולל את הנתונים שמאכלסים יומני נתיבי ניווט.

הפעלת דיווח על הסכמה

כברירת מחדל, Crashlytics אוסף באופן אוטומטי דוחות קריסה מכל המשתמשים באפליקציה. כדי לתת למשתמשים שליטה רבה יותר על הנתונים שהם שולחים, אפשר להפעיל דיווח על הסכמה מפורשת על ידי השבתת הדיווח האוטומטי ושליחת נתונים אל Crashlytics רק כשבוחרים בכך בקוד:

  1. כדי להשבית את האיסוף האוטומטי, מוסיפים מפתח חדש לקובץ Info.plist:

    • מפתח: FirebaseCrashlyticsCollectionEnabled
    • ערך: false
  2. כדי להפעיל את האיסוף למשתמשים נבחרים, צריך להפעיל את ההחרגה של איסוף הנתונים Crashlytics בזמן הריצה. ערך ההחרגה נשמר בכל ההפעלות של האפליקציה, כדי ש-Crashlytics יוכל לאסוף דוחות באופן אוטומטי.

    כדי לבטל את ההסכמה לדיווח אוטומטי על קריסות, צריך לקבוע את הערך של false בתור ערך הביטול. כשהערך מוגדר ל-false, הערך החדש לא יחול עד להפעלה הבאה של האפליקציה.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

ניהול הנתונים של 'תובנות לגבי קריסה'

התכונה 'תובנות לגבי קריסות' עוזרת לכם לפתור בעיות על ידי השוואה של נתוני המעקב אחרי סטאק (stack) שהוסרו מהם פרטי הזיהוי לנתוני מעקב מאפליקציות אחרות ב-Firebase, ומציינת אם הבעיה היא חלק ממגמה רחבה יותר. לגבי בעיות רבות, התכונה 'תובנות לגבי קריסות' מספקת גם מקורות מידע שיעזרו לכם לנפות את הבאגים שגרמו לקריסה.

התכונה 'תובנות לגבי קריסות' משתמשת בנתוני קריסות שנצברו כדי לזהות מגמות נפוצות ביציבות. אם לא רוצים לשתף את נתוני האפליקציה, אפשר לבטל את ההסכמה לשימוש ב'תובנות לגבי הקריסה'. בתפריט Crash Insights בראש רשימת הבעיות ב-Crashlytics במסוף Firebase.