Catch up on highlights from Firebase at Google I/O 2023. Learn more

تخصيص تقارير أعطال Firebase Crashlytics

يصف هذا الدليل كيفية تخصيص تقارير الأعطال باستخدام Firebase Crashlytics SDK. بشكل افتراضي ، تجمع Crashlytics تقارير الأعطال تلقائيًا لجميع مستخدمي تطبيقك (يمكنك إيقاف تشغيل إعداد تقارير الأعطال التلقائية وتمكين إعداد التقارير للمستخدمين بدلاً من ذلك). يوفر Crashlytics أربع آليات تسجيل خارج الصندوق: المفاتيح المخصصة والسجلات المخصصة ومعرفات المستخدم والاستثناءات التي تم التقاطها .

أضف مفاتيح مخصصة

تساعدك المفاتيح المخصصة في الحصول على الحالة المحددة لتطبيقك مما يؤدي إلى حدوث عطل. يمكنك ربط أزواج المفاتيح / القيم العشوائية بتقارير الأعطال ، ثم استخدام المفاتيح المخصصة للبحث عن تقارير الأعطال وتصفيتها في وحدة تحكم Firebase.

  • في لوحة معلومات Crashlytics ، يمكنك البحث عن المشكلات التي تطابق مفتاحًا مخصصًا.
  • عندما تقوم بمراجعة مشكلة معينة في وحدة التحكم ، يمكنك عرض المفاتيح المخصصة المرتبطة لكل حدث (علامة التبويب الفرعية Keys ) وحتى تصفية الأحداث حسب المفاتيح المخصصة (قائمة التصفية في الجزء العلوي من الصفحة).

استخدم طريقة 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 طريقة لتحديد هوية المستخدمين بشكل مجهول في تقارير الأعطال.

لإضافة معرّفات مستخدم إلى تقاريرك ، عيّن لكل مستخدم معرّفًا فريدًا في شكل رقم معرّف أو رمز مميز أو قيمة مجزأة:

سويفت

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 و -1001 . يتم تجميع الأخطاء الإضافية التي تم تسجيلها والتي تستخدم نفس المجال وقيم الرموز ضمن نفس المشكلة. يتم تحويل البيانات الموجودة في كائن userInfo إلى أزواج ذات قيمة مفتاح وعرضها في قسم المفاتيح / السجلات ضمن مشكلة فردية.

السجلات والمفاتيح المخصصة

تمامًا مثل تقارير الأعطال ، يمكنك تضمين السجلات والمفاتيح المخصصة لإضافة سياق إلى NSError . ومع ذلك ، هناك اختلاف في السجلات المرفقة بالأعطال مقابل الأخطاء المسجلة. عند حدوث عطل وإعادة تشغيل التطبيق ، فإن السجلات التي تستردها Crashlytics من القرص هي تلك التي تمت كتابتها حتى وقت التعطل. عندما تقوم بتسجيل NSError ، لا يتم إنهاء التطبيق على الفور. نظرًا لأن Crashlytics ترسل فقط تقرير الخطأ المسجل عند تشغيل التطبيق التالي ويجب أن تحد من مقدار المساحة المخصصة للسجلات على القرص ، فمن الممكن تسجيل ما يكفي بعد تسجيل NSError بحيث يتم تدوير جميع السجلات ذات الصلة بحلول الوقت الذي ترسل فيه Crashlytics التقرير من الجهاز. ضع هذا التوازن في الاعتبار عند تسجيل NSErrors واستخدام السجلات والمفاتيح المخصصة في تطبيقك.

اعتبارات الأداء

ضع في اعتبارك أن تسجيل NSError يمكن أن يكون مكلفًا إلى حد ما. في الوقت الذي تجري فيه المكالمة ، يلتقط Crashlytics مكدس مكالمات مؤشر الترابط الحالي باستخدام عملية تسمى فك المكدس. يمكن أن تكون هذه العملية مكثفة لوحدة المعالجة المركزية والإدخال / الإخراج ، لا سيما في البنى التي تدعم فك DWARF (arm64 و x86). بعد اكتمال الاسترخاء ، تتم كتابة المعلومات على القرص بشكل متزامن. هذا يمنع فقدان البيانات إذا تعطل السطر التالي.

بينما من الآمن استدعاء API هذا على مؤشر ترابط في الخلفية ، تذكر أن إرسال هذا الاستدعاء إلى قائمة انتظار أخرى يفقد سياق تتبع المكدس الحالي.

ماذا عن NSExceptions؟

لا تقدم Crashlytics وسيلة لتسجيل وتسجيل مثيلات NSException مباشرة. بشكل عام ، واجهات برمجة تطبيقات Cocoa و Cocoa Touch ليست آمنة من الاستثناءات. هذا يعني أن استخدام @catch يمكن أن يكون له آثار جانبية خطيرة للغاية غير مقصودة في عمليتك ، حتى عند استخدامه بحذر شديد. يجب ألا تستخدم عبارات @catch في التعليمات البرمجية الخاصة بك. يرجى الرجوع إلى وثائق Apple حول هذا الموضوع.

تخصيص آثار المكدس

إذا كان تطبيقك يعمل في بيئة غير أصلية (مثل C ++ أو Unity) ، فيمكنك استخدام Exception Model API للإبلاغ عن البيانات الوصفية التعطل بتنسيق الاستثناء الأصلي للتطبيق. تم وضع علامة على الاستثناءات المبلغ عنها على أنها غير مميتة.

سويفت

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)

ج موضوعية

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

يمكن أيضًا تهيئة إطارات المكدس المخصصة بعناوين فقط:

سويفت

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 Insights من قائمة Crash Insights أعلى قائمة مشكلات Crashlytics في وحدة تحكم Firebase .