Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

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

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

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

سويفت

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 البيانات في التعليمات البرمجية. يرجى الرجوع إلى وثائق أبل حول هذا الموضوع.

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

إذا كان تطبيقك يعمل في بيئة غير أصلية (مثل 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 بيانات الأعطال المجمعة لتحديد اتجاهات الاستقرار الشائعة. إذا كنت تفضل عدم مشاركة بيانات التطبيقات الخاصة بك، يمكنك اختيار عدم المشاركة في تحطم رؤى من القائمة تحطم البصائر في أعلى قائمة قضية Crashlytics الخاصة بك في وحدة التحكم Firebase .