Check out what’s new from Firebase@ Google I/O 2021, and join our alpha program for early access to the new Remote Config personalization feature. Learn more

התאם אישית את דוחות הקריסה של Firebase Crashlytics

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

הוסף מקשים מותאמים אישית

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

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

השתמש בשיטת setCustomValue כדי להגדיר זוגות מפתח / ערך. לדוגמה:

מָהִיר

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

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

מטרה-ג

כשמגדירים מספרים שלמים, בוליאנים או צפים, מסמנים את הערך כ- @( 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"];

אתה יכול גם לשנות את הערך של מפתח קיים על ידי התקשרות למפתח והגדרת אותו לערך אחר. לדוגמה:

מָהִיר

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

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

מטרה-ג

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

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

הוסף זוגות מפתח / ערך בכמויות גדולות על ידי שימוש בשיטת setCustomKeysAndValues עם NSDictionary כפרמטר היחיד:

מָהִיר

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)

מטרה-ג

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 , בכרטיסייה יומנים .

מָהִיר

השתמש ב- 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.

מטרה-ג

השתמש 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 כולל דרך לזהות משתמשים באופן אנונימי בדוחות הקריסה שלך.

כדי להוסיף מזהי משתמש לדוחות שלך, הקצה לכל משתמש מזהה ייחודי בצורת מספר מזהה, אסימון או ערך hashed:

מָהִיר
Crashlytics.crashlytics().setUserID("123456789")
מטרה-ג
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];

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

דווח על חריגים לא קטלניים

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

אתה יכול להקליט חריגים שאינם קטלניים על ידי הקלטת NSError חפץ עם recordError השיטה. recordError לוכדת את ערימת השיחות של השרשור על ידי קריאה ל- [NSThread callStackReturnAddresses] .

מָהִיר

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

מטרה-ג

[[FIRCrashlytics crashlytics] recordError:error];

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

לאובייקט NSError יש שלושה טיעונים:

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

שלא כמו קריסות קטלניות, המקובצות באמצעות ניתוח עקבות מחסנית, שגיאות מחוברות מקובצות לפי domain code . זו הבחנה חשובה בין התרסקויות קטלניות לבין שגיאות מחוברות. לדוגמה:

מָהִיר

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)

מטרה-ג

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 לפי NSSomeErrorDomain ו- -1001 . שגיאות מחוברות נוספות המשתמשות באותם ערכי תחום וקוד מקובצות תחת אותה בעיה. הנתונים הכלולים באובייקט userInfo מומרים לצמדי ערך מפתח ומוצגים בסעיף המפתחות / יומני הבעיה userInfo .

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

יומנים ומפתחות מותאמים אישית

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

שיקולי ביצועים

זכור כי רישום NSError יכול להיות יקר למדי. בזמן ביצוע השיחה, Crashlytics לוכדת את מחסנית השיחות של השרשור הנוכחי באמצעות תהליך הנקרא מחסנית. תהליך זה יכול להיות אינטנסיבי למעבד ו- I / O, במיוחד בארכיטקטורות התומכות בהסרת DWARF (arm64 ו- x86). לאחר השלמת הרגיעה, המידע נכתב לדיסק באופן סינכרוני. זה מונע אובדן נתונים אם השורה הבאה תקרוס.

אמנם בטוח להתקשר ל- API זה על שרשור רקע, אך זכור כי משלוח שיחה זו לתור אחר מאבד את ההקשר של עקבות הערימה הנוכחית.

מה לגבי NSExceptions?

Crashlytics אינו מציע מתקן לרישום והקלטה של ​​מופעי NSException באופן ישיר. באופן כללי, ממשקי ה- API של קקאו וקקאו טאץ 'אינם בטוחים במיוחד. כלומר, לשימוש ב- @catch יכולות להיות תופעות לוואי חמורות מאוד בתהליך שלך, גם כאשר משתמשים בזהירות רבה. לעולם אל תשתמש בהצהרות @catch בקוד שלך. אנא עיין בתיעוד של אפל בנושא.

התאם אישית את עקבות הערימה

אם האפליקציה שלך פועלת בסביבה שאינה מקורית (כגון C ++ או Unity), תוכל להשתמש בממשק ה- API של Exception Model כדי לדווח על מטא נתונים קריסה בפורמט החריג המקורי של האפליקציה שלך. חריגים שדווחו מסומנים כלא-קטלניים.

מָהִיר

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)

מטרה-ג

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],
];

[[FIRCrashlytics crashlytics] recordExceptionModel model];

ניתן לאתחל גם מסגרות ערימה מותאמות אישית עם כתובות בלבד:

מָהִיר

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)

מטרה-ג

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];

אפשר דיווח על הסכמה

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

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

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

    מָהִיר
    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
    מטרה-ג
    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

נהל נתוני Crash Insights

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

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