ปรับแต่งรายงานข้อขัดข้องของ Firebase Crashlytics

ในหน้าแดชบอร์ด Crashlytics คุณจะคลิกเข้าไปที่ปัญหาและรับรายงานเหตุการณ์โดยละเอียดได้ คุณปรับแต่งรายงานเหล่านั้นเพื่อช่วยให้คุณเข้าใจได้ดีขึ้นว่าเกิดอะไรขึ้นในแอปและสถานการณ์รอบเหตุการณ์ที่รายงานไปยัง Crashlytics

  • รับ บันทึกเบรดครัมบ์ โดยอัตโนมัติหากแอปของคุณใช้ Firebase SDK สำหรับ Google Analytics บันทึกเหล่านี้ช่วยให้คุณมองเห็นการกระทำของผู้ใช้ที่นำไปสู่เหตุการณ์ที่ 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")

วัตถุประสงค์-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"];

คุณยังสามารถแก้ไขค่าของคีย์ที่มีอยู่ได้โดยการเรียกคีย์แล้วตั้งค่าเป็นค่าอื่น ตัวอย่างเช่น:

สวิฟท์

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

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

วัตถุประสงค์-C

[[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)

วัตถุประสงค์-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 ใต้แท็บ บันทึก

สวิฟท์

ใช้ 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

วัตถุประสงค์-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 มีวิธีระบุผู้ใช้โดยไม่ระบุตัวตนในรายงานข้อขัดข้องของคุณ

หากต้องการเพิ่ม ID ผู้ใช้ลงในรายงานของคุณ ให้กำหนดตัวระบุที่ไม่ซ้ำกันให้กับผู้ใช้แต่ละรายในรูปแบบของหมายเลข ID โทเค็น หรือค่าแฮช:

สวิฟท์

Crashlytics.crashlytics().setUserID("123456789")

วัตถุประสงค์-C

[[FIRCrashlytics crashlytics] setUserID:@"123456789"];

หากคุณจำเป็นต้องล้างตัวระบุผู้ใช้หลังจากตั้งค่าแล้ว ให้รีเซ็ตค่าเป็นสตริงว่าง การล้างตัวระบุผู้ใช้จะไม่ลบบันทึก Crashlytics ที่มีอยู่ หากคุณต้องการลบบันทึกที่เกี่ยวข้องกับ ID ผู้ใช้ โปรด ติดต่อฝ่ายสนับสนุนของ Firebase

รายงานข้อยกเว้นที่ไม่ร้ายแรง

นอกเหนือจากการรายงานข้อขัดข้องของแอปโดยอัตโนมัติแล้ว Crashlytics ยังช่วยให้คุณบันทึกข้อยกเว้นที่ไม่ร้ายแรงและส่งให้คุณในครั้งถัดไปที่แอปของคุณเปิดตัว

คุณสามารถบันทึกข้อยกเว้นที่ไม่ร้ายแรงได้โดยการบันทึกวัตถุ NSError ด้วยเมธอด recordError recordError จับ call stack ของเธรดโดยการเรียก [NSThread callStackReturnAddresses]

สวิฟท์

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

วัตถุประสงค์-C

[[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)

วัตถุประสงค์-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 อย่างไรก็ตาม มีความแตกต่างในสิ่งที่แนบบันทึกกับข้อขัดข้องและข้อผิดพลาดที่บันทึกไว้ เมื่อเกิดข้อขัดข้องและแอปถูกเปิดใช้งานอีกครั้ง บันทึกที่ Crashlytics ดึงมาจากดิสก์จะเป็นบันทึกที่เขียนไว้จนถึงเวลาที่ข้อขัดข้อง เมื่อคุณบันทึก NSError แอปจะไม่ยุติการทำงานทันที เนื่องจาก Crashlytics จะส่งรายงานข้อผิดพลาดที่บันทึกไว้ในการเปิดแอปครั้งถัดไปเท่านั้น และต้องจำกัดจำนวนพื้นที่ที่จัดสรรสำหรับบันทึกบนดิสก์ คุณจึงสามารถบันทึกได้เพียงพอหลังจากบันทึก NSError เพื่อให้บันทึกที่เกี่ยวข้องทั้งหมดถูกหมุนเวียนออกไปตามเวลาที่ Crashlytics ส่ง รายงานจากอุปกรณ์ โปรดคำนึงถึงความสมดุลนี้เมื่อบันทึก NSErrors และใช้บันทึกและคีย์ที่กำหนดเองในแอปของคุณ

ข้อควรพิจารณาด้านประสิทธิภาพ

โปรดทราบว่าการบันทึก NSError อาจมีราคาค่อนข้างแพง เมื่อคุณทำการโทร Crashlytics จะบันทึกสแต็กการเรียกของเธรดปัจจุบันโดยใช้กระบวนการที่เรียกว่าการคลายสแต็ก กระบวนการนี้อาจต้องใช้ CPU และ I/O อย่างเข้มข้น โดยเฉพาะในสถาปัตยกรรมที่รองรับการคลี่คลาย DWARF (arm64 และ x86) หลังจากคลี่คลายเสร็จสิ้น ข้อมูลจะถูกเขียนลงดิสก์พร้อมกัน วิธีนี้จะช่วยป้องกันข้อมูลสูญหายหากบรรทัดถัดไปขัดข้อง

แม้ว่าการเรียก API นี้บนเธรดพื้นหลังจะปลอดภัย แต่โปรดจำไว้ว่าการส่งการเรียกนี้ไปยังคิวอื่นจะสูญเสียบริบทของการติดตามสแต็กปัจจุบัน

แล้ว NSExceptions ล่ะ?

Crashlytics ไม่มีสิ่งอำนวยความสะดวกในการบันทึกและบันทึกอินสแตนซ์ NSException โดยตรง โดยทั่วไปแล้ว Cocoa และ Cocoa Touch API นั้นไม่มีข้อยกเว้น นั่นหมายความว่าการใช้ @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)

วัตถุประสงค์-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];

เฟรมสแต็กแบบกำหนดเองสามารถเริ่มต้นได้ด้วยที่อยู่เพียง:

สวิฟท์

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)

วัตถุประสงค์-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 สำหรับ Google Analytics ลงในแอปของคุณ เมื่อปฏิบัติตามข้อกำหนดเหล่านี้ บันทึกเบรดครัมบ์จะรวมเข้ากับข้อมูลของเหตุการณ์ภายในแท็บ บันทึก โดยอัตโนมัติเมื่อคุณดูรายละเอียดของปัญหา

Analytics SDK จะบันทึกเหตุการณ์ screen_view โดยอัตโนมัติ ซึ่งช่วยให้บันทึกเบรดครัมบ์แสดงรายการหน้าจอที่ดูก่อนเหตุการณ์ขัดข้อง เหตุการณ์ที่ไม่ร้ายแรง หรือ ANR บันทึกการแสดงเส้นทาง screen_view มีพารามิเตอร์ firebase_screen_class

บันทึกเบรดครัมบ์ยังถูกเติมด้วย เหตุการณ์ที่กำหนดเอง ใดๆ ที่คุณบันทึกด้วยตนเองภายในเซสชันของผู้ใช้ รวมถึงข้อมูลพารามิเตอร์ของเหตุการณ์ด้วย ข้อมูลนี้สามารถช่วยแสดงชุดการดำเนินการของผู้ใช้ที่นำไปสู่เหตุการณ์ขัดข้อง เหตุการณ์ที่ไม่ร้ายแรง หรือ ANR

โปรดทราบว่าคุณสามารถ ควบคุมการรวบรวมและการใช้ข้อมูล Google Analytics ซึ่งรวมถึงข้อมูลที่เติมบันทึกการแสดงเส้นทาง

เปิดใช้งานการรายงานการเลือกเข้าร่วม

ตามค่าเริ่มต้น Crashlytics จะรวบรวมรายงานข้อขัดข้องสำหรับผู้ใช้แอปทั้งหมดของคุณโดยอัตโนมัติ เพื่อให้ผู้ใช้ควบคุมข้อมูลที่ส่งได้มากขึ้น คุณสามารถเปิดใช้การรายงานแบบเลือกรับได้โดยปิดใช้การรายงานอัตโนมัติ และส่งข้อมูลไปยัง Crashlytics เมื่อคุณเลือกในโค้ดของคุณเท่านั้น:

  1. ปิดการรวบรวมอัตโนมัติโดยเพิ่มคีย์ใหม่ลงในไฟล์ Info.plist ของคุณ:

    • คีย์: FirebaseCrashlyticsCollectionEnabled
    • ค่า: false
  2. เปิดใช้การรวบรวมสำหรับผู้ใช้ที่เลือกโดยเรียกใช้การลบล้างการรวบรวมข้อมูล Crashlytics ณ รันไทม์ ค่าแทนที่จะยังคงอยู่ตลอดการเปิดตัวแอปของคุณ ดังนั้น Crashlytics จึงรวบรวมรายงานได้โดยอัตโนมัติ

    หากต้องการเลือกไม่ใช้การรายงานข้อขัดข้องอัตโนมัติ ให้ส่ง false เป็นค่าแทนที่ เมื่อตั้งค่าเป็น false ค่าใหม่จะไม่มีผลจนกว่าจะมีการเรียกใช้แอปครั้งถัดไป

    สวิฟท์

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    วัตถุประสงค์-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

จัดการข้อมูล Crash Insights

Crash Insights ช่วยคุณแก้ไขปัญหาโดยการเปรียบเทียบสแต็กเทรซที่ไม่ระบุตัวตนกับการติดตามจากแอป Firebase อื่นๆ และแจ้งให้คุณทราบว่าปัญหาของคุณเป็นส่วนหนึ่งของเทรนด์ที่ใหญ่กว่าหรือไม่ สำหรับปัญหาต่างๆ มากมาย Crash Insights ยังมีทรัพยากรเพื่อช่วยคุณแก้ไขจุดบกพร่องอีกด้วย

Crash Insights ใช้ข้อมูลข้อขัดข้องที่รวบรวมไว้เพื่อระบุแนวโน้มความเสถียรทั่วไป หากคุณไม่ต้องการแชร์ข้อมูลแอป คุณสามารถเลือกไม่รับ Crash Insights ได้จากเมนู Crash Insights ที่ด้านบนของรายการปัญหา Crashlytics ใน คอนโซล Firebase