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


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

  • الحصول على سجلات شريط التنقل تلقائيًا إذا كان تطبيقك يستخدم حزمة تطوير البرامج (SDK) لمنصّة Firebase الخاصة بالإصدار 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، ضمن علامة التبويب السجلّات.

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 إلى أزواج مفتاح/قيمة ويتم عرضها في قسم المفاتيح/السجلّات ضمن مشكلة فردية.

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

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

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

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

بينما يكون الاتصال من خلال واجهة برمجة التطبيقات هذه على سلسلة محادثات في الخلفية، فتذكر أن إرسال هذا الاتصال إلى تفقد قائمة الانتظار سياق تتبُّع تسلسل استدعاء الدوال البرمجية الحالي.

ماذا عن NSالاستثناءات؟

لا يوفّر "Crashlytics" وسيلة لتسجيل وتسجيل "NSException" الحالات مباشرةً. بشكل عام، لا تكون واجهات برمجة التطبيقات Cocoa وCocoa Touch خالية من الأخطاء. وهذا يعني أنّ استخدام @catch يمكن أن يؤدي إلى آثار جانبية unintended خطيرة جدًا في عملية المعالجة، حتى عند استخدامه بحذر شديد. لا ينبغي عليك أبدًا استخدام عبارات @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];

الحصول على سجلات شريط التنقل

تمنحك سجلات "المسار إلى الصفحة" فهمًا أفضل للتفاعلات التي أجراها أحد المستخدِمين مع تطبيقك قبل حدوث تعذُّر أو حدث خطأ غير قاتل أو ANR. يمكن أن تكون هذه السجلّات مفيدة عند محاولة إعادة إظهار مشكلة وتصحيح أخطاءها.

يتم دعم سجلات شريط التنقل من خلال Google Analytics، وبالتالي للحصول على سجلات شريط التنقل، بحاجة إلى تفعيل "إحصاءات Google" لمشروعك على Firebase إضافة حزمة تطوير البرامج (SDK) لمنصة Firebase للموقع الإلكتروني 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];

إدارة بيانات "إحصاءات الأعطال"

تساعدك ميزة "إحصاءات الأعطال" في حلّ المشاكل من خلال مقارنة عمليات التتبّع الخاصة بك والتي تم إخفاء هويتها بعمليات التتبّع من تطبيقات Firebase الأخرى وإعلامك إذا كانت مشكلتك جزءًا من مؤشر أكبر. بالنسبة إلى العديد من المشاكل، توفّر ميزة "إحصاءات الأعطال" مراجع أيضًا. لمساعدتك في تصحيح العطل.

تستخدم "إحصاءات الأعطال" بيانات الأعطال المجمّعة لتحديد مؤشرات الاستقرار الشائعة. إذا كنت تفضّل عدم مشاركة بيانات تطبيقك، يمكنك إيقاف ميزة "إحصاءات الأعطال" من قائمة إحصاءات الأعطال في أعلى قائمة CrashlyticsCrashlytics في وحدة تحكّم Firebase.