Hiểu rõ sự cố của trò chơi Unity bằng các tính năng nâng cao của Crashlytics

1. Giới thiệu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách sử dụng các tính năng nâng cao của Crashlytics để hiểu rõ hơn về các sự cố và những trường hợp có thể gây ra sự cố.

Bạn sẽ thêm chức năng mới vào một trò chơi mẫu, MechaHamster: Nâng cấp cùng phiên bản Firebase. Trò chơi mẫu này là phiên bản mới của trò chơi MechaHamster cổ điển trên Firebase. Trò chơi này sẽ loại bỏ hầu hết chức năng Firebase tích hợp sẵn, cho bạn cơ hội triển khai những cách sử dụng Firebase mới thay cho chúng.

Bạn sẽ thêm một trình đơn gỡ lỗi vào trò chơi. Trình đơn gỡ lỗi này gọi các phương thức mà bạn sẽ tạo và cho phép bạn thực hiện các chức năng của Crashlytics. Các phương pháp này sẽ hướng dẫn bạn cách chú thích báo cáo sự cố tự động bằng các khoá tuỳ chỉnh, nhật ký tuỳ chỉnh, lỗi không nghiêm trọng, v.v.

Sau khi xây dựng trò chơi, bạn sẽ sử dụng trình đơn gỡ lỗi, đồng thời kiểm tra kết quả để hiểu chế độ xem riêng biệt mà chúng cung cấp về cách trò chơi của bạn chạy trong tự nhiên.

Kiến thức bạn sẽ học được

  • Các loại lỗi mà Crashlytics phát hiện tự động.
  • Các lỗi khác có thể được ghi lại có chủ đích.
  • Cách bổ sung thông tin vào những lỗi này để chúng dễ hiểu hơn.

Bạn cần có

2. Thiết lập môi trường phát triển

Các phần sau mô tả cách tải mã Lên cấp cùng Firebase xuống rồi mở mã đó trong Unity.

Lưu ý rằng trò chơi mẫu Nâng cấp cùng Firebase được một số lớp học lập trình khác của Firebase + Unity sử dụng, vì vậy có thể bạn đã hoàn tất các nhiệm vụ trong phần này. Nếu có, bạn có thể chuyển thẳng đến bước cuối cùng trên trang này: "Thêm Firebase SDK cho Unity".

Tải đoạn mã

Sao chép kho lưu trữ GitHub của lớp học lập trình này từ dòng lệnh:

git clone https://github.com/firebase/level-up-with-firebase.git

Ngoài ra, nếu chưa cài đặt git, bạn có thể tải kho lưu trữ xuống dưới dạng tệp ZIP.

Mở trang Nâng cấp cùng Firebase trong trình chỉnh sửa Unity

  1. Khởi chạy Unity Hub và từ thẻ Projects (Dự án), hãy nhấp vào mũi tên thả xuống bên cạnh nút Open (Mở).
  2. Nhấp vào Thêm dự án từ ổ đĩa.
  3. Chuyển đến thư mục chứa mã, sau đó nhấp vào OK.
  4. Nếu được nhắc, hãy chọn một phiên bản trình chỉnh sửa Unity để sử dụng và nền tảng đích của bạn (Android hoặc iOS).
  5. Nhấp vào tên dự án level-up-with-firebase và dự án sẽ mở trong trình chỉnh sửa Unity.
  6. Nếu trình chỉnh sửa không tự động mở tệp, hãy mở MainGameScene trong phần Nội dung > Hamster trong thẻ Project (Dự án) của Trình chỉnh sửa Unity.
    ff4ea3f3c0d29379.pngS

Để biết thêm thông tin về cách cài đặt và sử dụng Unity, hãy xem bài viết Làm việc trong Unity.

3. Thêm Firebase vào dự án Unity

Tạo một dự án Firebase

  1. Trong bảng điều khiển của Firebase, hãy nhấp vào Thêm dự án.
  2. Để tạo một dự án mới, hãy nhập tên dự án mà bạn muốn.
    Thao tác này cũng sẽ thiết lập mã dự án (hiển thị bên dưới tên dự án) thành một giá trị nào đó dựa trên tên dự án. Bạn có thể nhấp vào biểu tượng chỉnh sửa trên mã dự án để tuỳ chỉnh thêm (không bắt buộc).
  3. Nếu được nhắc, hãy xem xét và chấp nhận các điều khoản của Firebase.
  4. Nhấp vào Tiếp tục.
  5. Chọn mục Bật Google Analytics cho dự án này, rồi nhấp vào Tiếp tục.
  6. Chọn tài khoản Google Analytics hiện có để sử dụng hoặc chọn Tạo tài khoản mới để tạo tài khoản mới.
  7. Nhấp vào Tạo dự án.
  8. Sau khi tạo dự án, hãy nhấp vào Tiếp tục.

Đăng ký ứng dụng của bạn với Firebase

  1. Vẫn trong bảng điều khiển của Firebase, ở giữa trang tổng quan về dự án, hãy nhấp vào biểu tượng Unity để chạy quy trình thiết lập hoặc nếu bạn đã thêm một ứng dụng vào dự án Firebase, hãy nhấp vào Thêm ứng dụng để hiển thị các lựa chọn về nền tảng.
  2. Chọn đăng ký cả mục tiêu bản dựng của Apple (iOS) và Android.
  3. Nhập(các) mã nhận dạng dành riêng cho nền tảng của dự án Unity. Đối với lớp học lập trình này, hãy nhập nội dung sau:
  4. (Không bắt buộc) Nhập(các) biệt hiệu dành riêng cho nền tảng của dự án Unity.
  5. Nhấp vào Đăng ký ứng dụng, sau đó tiếp tục chuyển đến phần Tải tệp cấu hình xuống.

Thêm tệp cấu hình Firebase

Sau khi nhấp vào Đăng ký ứng dụng, bạn sẽ được nhắc tải hai tệp cấu hình xuống (một tệp cấu hình cho mỗi mục tiêu bản dựng). Dự án Unity của bạn cần siêu dữ liệu Firebase trong các tệp này để kết nối với Firebase.

  1. Tải xuống cả hai tệp cấu hình có sẵn:
    • Đối với Apple (iOS): Tải GoogleService-Info.plist xuống.
    • Đối với Android: Tải tệp google-services.json xuống.
  2. Mở cửa sổ Project (Dự án) của dự án Unity, sau đó di chuyển cả hai tệp cấu hình vào thư mục Assets (Tài sản).
  3. Quay lại bảng điều khiển của Firebase, trong quy trình thiết lập, hãy nhấp vào Tiếp theo rồi chuyển sang Thêm SDK Firebase cho Unity.

Thêm Firebase SDK cho Unity

  1. Nhấp vào Tải Firebase Unity SDK xuống trong bảng điều khiển của Firebase.
  2. Giải nén SDK ở nơi thuận tiện.
  3. Trong Dự án Unity đang mở, hãy chuyển đến Assets (Tài sản) > Nhập gói > Gói tuỳ chỉnh.
  4. Trong hộp thoại Import package (Nhập gói), hãy chuyển đến thư mục chứa SDK đã giải nén, chọn FirebaseAnalytics.unitypackage rồi nhấp vào Open (Mở).
  5. Khi hộp thoại Import Unity Package (Nhập gói Unity) xuất hiện, hãy nhấp vào Import (Nhập).
  6. Lặp lại các bước trước đó để nhập FirebaseCrashlytics.unitypackage.
  7. Quay lại bảng điều khiển của Firebase, rồi nhấp vào Tiếp theo trong quy trình thiết lập.

Để biết thêm thông tin về cách thêm Firebase SDK vào dự án Unity, hãy xem Các tuỳ chọn cài đặt Unity bổ sung.

4. Thiết lập Crashlytics trong dự án Unity

Để sử dụng Crashlytics trong các dự án Unity, bạn cần thực hiện thêm một vài bước thiết lập. Tất nhiên, bạn cần phải khởi chạy SDK. Ngoài ra, bạn cần tải các biểu tượng lên để có thể thấy các dấu vết ngăn xếp được thay thế bằng biểu tượng trong bảng điều khiển của Firebase, đồng thời bạn cần thực hiện kiểm thử sự cố để đảm bảo rằng Firebase sẽ nhận được các sự kiện sự cố của bạn.

Chạy Crashlytics SDK

  1. Trong Assets/Hamster/Scripts/MainGame.cs, hãy thêm các câu lệnh using sau:
    using Firebase.Crashlytics;
    using Firebase.Extensions;
    
    Mô-đun đầu tiên cho phép bạn sử dụng các phương thức từ Crashlytics SDK và mô-đun thứ hai chứa một số tiện ích cho C# Tasks API. Nếu không có cả hai câu lệnh using, thì mã sau sẽ không hoạt động.
  2. Vẫn trong MainGame.cs, hãy thêm tính năng khởi chạy Firebase vào phương thức Start() hiện có bằng cách gọi InitializeFirebaseAndStartGame():
    void Start()
    {
      Screen.SetResolution(Screen.width / 2, Screen.height / 2, true);
      InitializeFirebaseAndStartGame();
    }
    
  3. Và một lần nữa, trong MainGame.cs, hãy tìm InitializeFirebaseAndStartGame(), khai báo một biến ứng dụng, sau đó ghi đè phương thức triển khai của phương thức như sau:
    public Firebase.FirebaseApp app = null;
    
    // Begins the firebase initialization process and afterwards, opens the main menu.
    private void InitializeFirebaseAndStartGame()
    {
      Firebase.FirebaseApp.CheckAndFixDependenciesAsync()
      .ContinueWithOnMainThread(
        previousTask => 
        {
          var dependencyStatus = previousTask.Result;
          if (dependencyStatus == Firebase.DependencyStatus.Available) {
            // Create and hold a reference to your FirebaseApp,
            app = Firebase.FirebaseApp.DefaultInstance;
            // Set the recommended Crashlytics uncaught exception behavior.
            Crashlytics.ReportUncaughtExceptionsAsFatal = true;
            InitializeCommonDataAndStartGame();
          } else {
            UnityEngine.Debug.LogError(
              $"Could not resolve all Firebase dependencies: {dependencyStatus}\n" +
              "Firebase Unity SDK is not safe to use here");
          }
        });
    }
    

Việc đặt logic khởi động ở đây sẽ ngăn người chơi tương tác trước khi khởi chạy các phần phụ thuộc Firebase.

Lợi ích và tác động của việc báo cáo trường hợp ngoại lệ không được xử lý (là nghiêm trọng) sẽ được thảo luận trong Câu hỏi thường gặp về Crashlytics.

Xây dựng dự án và tải biểu tượng lên

Các bước tạo và tải biểu tượng lên sẽ khác nhau đối với ứng dụng iOS và Android.

iOS+ (nền tảng của Apple)

  1. Từ hộp thoại Build Settings (Cài đặt bản dựng), hãy xuất dự án của bạn sang không gian làm việc trên Xcode.
  2. Tạo ứng dụng của bạn.
    Đối với các nền tảng của Apple, trình bổ trợ Trình chỉnh sửa Firebase Unity sẽ tự động định cấu hình dự án Xcode của bạn để tạo và tải một tệp biểu tượng tương thích với Crashlytics lên máy chủ Firebase cho từng bản dựng. Bạn cần có thông tin về biểu tượng này để xem được dấu vết ngăn xếp được thay thế bằng biểu tượng trên trang tổng quan Crashlytics.

Android

  1. (chỉ trong quá trình thiết lập ban đầu, không áp dụng cho từng bản dựng) Thiết lập bản dựng:
    1. Tạo một thư mục mới có tên Builds (Bản dựng) ở gốc thư mục dự án (tức là thư mục đồng cấp với thư mục Assets) sau đó tạo một thư mục con có tên là Android.
    2. Trong Tệp > Cài đặt bản dựng > Cài đặt trình phát > Cấu hình, đặt Phần phụ trợ tập lệnh thành IL2CPP.
      • IL2CPP thường làm cho các bản dựng nhỏ hơn và có hiệu suất tốt hơn.
      • IL2CPP cũng là tuỳ chọn CHỈ có sẵn trên iOS và việc chọn IL2CPP ở đây cho phép hai nền tảng tương đương hơn và làm cho việc gỡ lỗi khác biệt giữa hai nền tảng này (nếu bạn chọn xây dựng cả hai) đơn giản hơn.
  2. Xây dựng ứng dụng của bạn. Trong Tệp > Build Settings (Cài đặt bản dựng), hãy hoàn thành các bước sau:
    1. Hãy đảm bảo rằng bạn đã đánh dấu vào Create Đã chọn.zip (hoặc nếu bạn thấy một trình đơn thả xuống, hãy chọn Debug (Gỡ lỗi)).
    2. Tạo APK trực tiếp từ Trình chỉnh sửa Unity vào thư mục con Builds/Android mà bạn vừa tạo.
  3. Sau khi bản dựng hoàn tất, bạn cần tạo một tệp biểu tượng tương thích với Crashlytics rồi tải tệp đó lên máy chủ Firebase. Bạn cần có thông tin về biểu tượng này để xem dấu vết ngăn xếp được thay thế bằng biểu tượng cho các sự cố thư viện gốc trên trang tổng quan Crashlytics.

    Tạo và tải tệp biểu tượng này lên bằng cách chạy lệnh Firebase CLI sau đây:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
    • FIREBASE_APP_ID: Mã ứng dụng Android trên Firebase (không phải tên gói). Tìm giá trị này trong tệp google-services.json mà bạn đã tải xuống trước đó. Đó là giá trị mobilesdk_app_id.
      Mã ứng dụng Android Firebase mẫu: 1:567383003300:android:17104a2ced0c9b9b
    • PATH/TO/SYMBOLS: đường dẫn của tệp biểu tượng nén được tạo trong thư mục Builds/Android khi bản dựng hoàn tất (ví dụ: Builds/Android/myapp-1.0-v100.symbols.zip).

Xác định sự cố thử nghiệm để hoàn tất việc thiết lập

Để hoàn tất việc thiết lập Crashlytics và xem dữ liệu ban đầu trên trang tổng quan Crashlytics trong bảng điều khiển của Firebase, bạn cần xác định sự cố thử nghiệm.

  1. Trong MainGameScene, hãy tìm EmptyObjectGameObject trong trình chỉnh sửa Phân cấp, thêm tập lệnh sau vào tệp đó rồi lưu cảnh. Tập lệnh này sẽ gây ra sự cố kiểm thử vài giây sau khi bạn chạy ứng dụng.
    using System;
    using UnityEngine;
    
    public class CrashlyticsTester : MonoBehaviour {
        // Update is called once per frame
        void Update()
        {
            // Tests your Crashlytics implementation by
            // throwing an exception every 60 frames.
            // You should see reports in the Firebase console
            // a few minutes after running your app with this method.
            if(Time.frameCount >0 && (Time.frameCount%60) == 0)
            {
                throw new System.Exception("Test exception; please ignore");
            }
        }
    }
    
  2. Tạo ứng dụng và tải thông tin biểu tượng lên sau khi hoàn tất bản dựng.
    • iOS: Trình bổ trợ Firebase Unity Editor sẽ tự động định cấu hình dự án Xcode để tải tệp biểu tượng của bạn lên.
    • Android: Chạy lệnh crashlytics:symbols:upload CLI của Firebase để tải tệp biểu tượng lên.
  3. Chạy ứng dụng. Khi ứng dụng của bạn đang chạy, hãy xem nhật ký thiết bị và chờ ngoại lệ kích hoạt từ CrashlyticsTester.
    • iOS: Xem nhật ký trong ngăn dưới cùng của Xcode.
    • Android: Xem nhật ký bằng cách chạy lệnh sau trong cửa sổ dòng lệnh: adb logcat.
  4. Hãy truy cập vào trang tổng quan của Crashlytics để xem trường hợp ngoại lệ! Bạn sẽ thấy vấn đề này trong bảng Vấn đề ở cuối trang tổng quan. Trong phần sau của lớp học lập trình này, bạn sẽ tìm hiểu thêm về cách khám phá các báo cáo này.
  5. Sau khi bạn xác nhận rằng sự kiện đã được tải lên Crashlytics, hãy chọn EmptyObject GameObject mà bạn đã đính kèm, chỉ xoá thành phần CrashlyticsTester, rồi lưu cảnh để khôi phục về tình trạng ban đầu.

5. Bật và tìm hiểu Trình đơn gỡ lỗi

Cho đến nay, bạn đã thêm Crashlytics vào dự án Unity, hoàn tất việc thiết lập và xác nhận rằng Crashlytics SDK đang tải các sự kiện lên Firebase. Bây giờ, bạn sẽ tạo một trình đơn trong dự án Unity để minh hoạ cách sử dụng chức năng Crashlytics nâng cao hơn trong trò chơi của bạn. Dự án Unity Lên cấp cùng Firebase đã có một Trình đơn gỡ lỗi ẩn mà bạn sẽ hiển thị và viết chức năng.

Bật trình đơn gỡ lỗi

Nút truy cập Trình đơn gỡ lỗi đã tồn tại trong dự án Unity của bạn, nhưng hiện chưa được bật. Bạn phải bật nút để truy cập vào nút này từ prefab MainMenu:

  1. Trong Trình chỉnh sửa Unity, hãy mở prefab có tên MainMenu.4148538cbe9f36c5.pngS
  2. Trong hệ phân cấp prefab, hãy tìm đối tượng phụ bị vô hiệu hoá có tên là DebugMenuButton rồi chọn đối tượng đó.816f8f9366280f6c.png.
  3. Bật DebugMenuButton bằng cách đánh dấu vào hộp ở góc trên bên trái phía bên trái của trường văn bản chứa DebugMenuButton.8a8089d2b4886da2.pngS
  4. Lưu prefab.
  5. Chạy trò chơi trong trình chỉnh sửa hoặc trên thiết bị của bạn. Lúc này, bạn có thể truy cập vào trình đơn.

Xem trước và tìm hiểu về các phần nội dung phương thức cho Trình đơn gỡ lỗi

Trong phần sau của lớp học lập trình này, bạn sẽ viết nội dung phương thức cho một số phương thức gỡ lỗi Crashlytics được định cấu hình sẵn. Tuy nhiên, trong dự án Unity Lên cấp với Firebase, các phương thức được xác định trong và được gọi từ DebugMenu.cs.

Mặc dù một số phương thức trong số này sẽ gọi cả phương thức Crashlytics và báo cáo lỗi, nhưng khả năng Crashlytics phát hiện các lỗi này không phụ thuộc vào việc gọi các phương thức đó trước tiên. Thay vào đó, báo cáo sự cố được tạo từ tính năng tự động phát hiện lỗi sẽ được cải thiện bằng thông tin được thêm bằng các phương pháp này.

Mở DebugMenu.cs rồi tìm các phương thức sau:

Phương thức tạo và chú thích các vấn đề trong Crashlytics:

  • CrashNow
  • LogNonfatalError
  • LogStringsAndCrashNow
  • SetAndOverwriteCustomKeyThenCrash
  • SetLogsAndKeysBeforeANR

Các phương thức để ghi nhật ký sự kiện Analytics nhằm hỗ trợ gỡ lỗi:

  • LogProgressEventWithStringLiterals
  • LogIntScoreWithBuiltInEventAndParams

Trong các bước sau của lớp học lập trình này, bạn sẽ triển khai các phương thức này và tìm hiểu cách chúng giúp giải quyết các tình huống cụ thể có thể xảy ra trong quá trình phát triển trò chơi.

6. Đảm bảo phân phối báo cáo sự cố trong quá trình phát triển

Trước khi bắt đầu triển khai các phương thức gỡ lỗi này và xem chúng ảnh hưởng như thế nào đến báo cáo sự cố, hãy đảm bảo bạn hiểu cách các sự kiện được báo cáo cho Crashlytics.

Đối với các dự án Unity, các sự kiện sự cố và ngoại lệ trong trò chơi của bạn sẽ được ghi ngay lập tức vào ổ đĩa. Đối với các trường hợp ngoại lệ chưa nắm bắt không gây ra sự cố trong trò chơi (ví dụ: chưa nắm bắt được ngoại lệ C# trong logic trò chơi), bạn có thể để Crashlytics SDK báo cáo chúng là sự kiện nghiêm trọng bằng cách đặt thuộc tính Crashlytics.ReportUncaughtExceptionsAsFatal thành true tại nơi bạn khởi chạy Crashlytics trong dự án Unity. Những sự kiện này được báo cáo cho Crashlytics theo thời gian thực mà không cần người dùng cuối khởi động lại trò chơi. Xin lưu ý rằng các sự cố gốc luôn được báo cáo là sự kiện nghiêm trọng và được gửi đi khi người dùng cuối khởi động lại trò chơi.

Ngoài ra, hãy lưu ý những điểm khác biệt nhỏ nhưng đáng kể sau đây giữa cách các môi trường thời gian chạy khác nhau gửi thông tin Crashlytics đến Firebase:

Trình mô phỏng iOS:

  • Thông tin Crashlytics được báo cáo khi và chỉ khi bạn tách Xcode khỏi trình mô phỏng. Nếu bạn đính kèm Xcode, công cụ này sẽ phát hiện lỗi ngược dòng, ngăn chặn việc phân phối thông tin.

Thiết bị di động thực (Android và iOS):

  • Dành riêng cho Android: Lỗi ANR chỉ được báo cáo trên Android 11 trở lên. Các sự kiện ANR và sự kiện không nghiêm trọng sẽ được báo cáo trong lần chạy tiếp theo.

Trình chỉnh sửa Unity:

Thử nghiệm sự cố trò chơi bằng cách nhấn vào nút trong CrashNow()

Sau khi Crashlytics được thiết lập trong trò chơi của bạn, Crashlytics SDK sẽ tự động ghi lại các sự cố và trường hợp ngoại lệ chưa nắm bắt được rồi tải chúng lên Firebase để phân tích. Các báo cáo sẽ xuất hiện trên trang tổng quan Crashlytics trong bảng điều khiển của Firebase.

  1. Để chứng minh rằng đây thực sự là quá trình tự động: hãy mở DebugMenu.cs rồi ghi đè phương thức CrashNow() như sau:
    void CrashNow()
    {
        TestCrash();
    }
    
  2. Xây dựng ứng dụng của bạn.
  3. (Chỉ dành cho Android) Tải các biểu tượng của bạn lên bằng cách chạy lệnh CLI Firebase sau:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Nhấn vào nút Crash Now (Sự cố ngay) rồi chuyển sang bước tiếp theo của lớp học lập trình này để tìm hiểu cách xem và diễn giải báo cáo sự cố.

7. Tìm hiểu về báo cáo vấn đề trong bảng điều khiển của Firebase

Khi xem báo cáo sự cố, bạn cần biết thêm một số thông tin về cách tận dụng tối đa những báo cáo này. Mỗi phương thức bạn viết sẽ cho biết cách thêm các loại thông tin khác nhau vào báo cáo Crashlytics.

  1. Nhấn vào nút Crash Now (Sự cố ngay) rồi khởi động lại ứng dụng.
  2. Chuyển đến trang tổng quan Crashlytics. Di chuyển xuống bảng Vấn đề ở cuối trang tổng quan. Tại đây, Crashlytics nhóm các sự kiện có cùng nguyên nhân gốc thành "vấn đề".
  3. Nhấp vào vấn đề mới trên bảng Vấn đề. Thao tác này sẽ hiển thị Tóm tắt sự kiện về từng sự kiện riêng lẻ được gửi đến Firebase.

    Bạn sẽ thấy nội dung giống như ảnh chụp màn hình sau đây. Hãy lưu ý cách mục Tóm tắt sự kiện hiển thị nổi bật dấu vết ngăn xếp của lệnh gọi dẫn đến sự cố.40c96abe7f90c3aa.pngS

Siêu dữ liệu bổ sung

Một thẻ hữu ích khác là thẻ Unity Metadata (Siêu dữ liệu Unity). Phần này thông báo cho bạn về các thuộc tính của thiết bị nơi sự kiện xảy ra, bao gồm các tính năng thực, mẫu/thông số kỹ thuật của CPU và tất cả các loại chỉ số GPU.

Sau đây là một ví dụ mà thông tin trong thẻ này có thể hữu ích:
Giả sử trò chơi của bạn sử dụng nhiều chương trình đổ bóng để tạo ra một giao diện nhất định, nhưng không phải điện thoại nào cũng có GPU có khả năng kết xuất tính năng này. Thông tin trong thẻ Siêu dữ liệu Unity có thể giúp bạn hiểu rõ hơn về những phần cứng mà ứng dụng của bạn nên kiểm thử khi quyết định những tính năng nào sẽ tự động được cung cấp hoặc tắt hoàn toàn.

Mặc dù lỗi hoặc sự cố có thể không bao giờ xảy ra trên thiết bị của bạn, nhưng do có rất nhiều thiết bị Android trong môi trường hoang dã, điều này giúp bạn hiểu rõ hơn về các "điểm nóng" cụ thể trên thiết bị của độc giả.

41d8d7feaa87454d.png.

8. Ném, phát hiện và ghi lại ngoại lệ

Thông thường, là một nhà phát triển, ngay cả khi mã của bạn nắm bắt và xử lý đúng cách một ngoại lệ thời gian chạy, bạn vẫn nên lưu ý rằng lỗi đó đã xảy ra và trong trường hợp nào. Bạn có thể sử dụng Crashlytics.LogException cho mục đích chính xác này – để gửi một sự kiện ngoại lệ đến Firebase để bạn có thể tiếp tục khắc phục vấn đề trong bảng điều khiển của Firebase.

  1. Trong Assets/Hamster/Scripts/States/DebugMenu.cs, hãy thêm nội dung sau vào câu lệnh using:
    // Import Firebase
    using Firebase.Crashlytics;
    
  2. Vẫn trong DebugMenu.cs, hãy ghi đè LogNonfatalError() như sau:
    void LogNonfatalError()
    {
        try
        {
            throw new System.Exception($"Test exception thrown in {nameof(LogNonfatalError)}");
        }
        catch(System.Exception exception)
        {
            Crashlytics.LogException(exception);
        }
    }
    
  3. Xây dựng ứng dụng của bạn.
  4. (Chỉ dành cho Android) Tải các biểu tượng của bạn lên bằng cách chạy lệnh CLI Firebase sau:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  5. Nhấn vào nút Log NonCritical Error (Ghi nhật ký lỗi không nghiêm trọng) rồi khởi động lại ứng dụng.
  6. Truy cập vào trang tổng quan Crashlytics và bạn sẽ thấy nội dung tương tự như những gì đã thấy trong bước cuối cùng của lớp học lập trình này.
  7. Tuy nhiên, lần này hãy hạn chế bộ lọc Loại sự kiện thành Không nghiêm trọng để bạn chỉ xem các lỗi không nghiêm trọng, chẳng hạn như lỗi bạn vừa ghi lại.
    a39ea8d9944cbbd9.png.

9. Chuỗi nhật ký lên Crashlytics để hiểu rõ hơn về quy trình thực thi chương trình

Bạn đã bao giờ tìm hiểu lý do tại sao một dòng mã được gọi từ nhiều đường dẫn (hàng trăm hoặc hàng nghìn lần trong mỗi phiên) có thể đột nhiên tạo ra ngoại lệ hoặc sự cố chưa? Mặc dù có thể tốt hơn khi duyệt qua mã trong IDE và xem xét kỹ hơn các giá trị, nhưng điều gì sẽ xảy ra nếu điều này chỉ xảy ra với một tỷ lệ nhỏ người dùng của bạn? Thậm chí tệ hơn, bạn sẽ làm gì nếu không thể tái tạo sự cố này bất kể bạn có làm gì?

Trong những tình huống như thế này, việc có được bối cảnh nào đó có thể tạo nên sự khác biệt. Với Crashlytics.Log, bạn có thể viết ra ngữ cảnh mà bạn cần. Hãy xem những thông điệp này là gợi ý cho bản thân trong tương lai về những gì có thể xảy ra.

Mặc dù nhật ký có thể được sử dụng theo nhiều cách, nhưng nhật ký thường hữu ích nhất trong việc ghi lại các tình huống trong đó thứ tự và/hoặc không có cuộc gọi là thông tin cực kỳ quan trọng.

  1. Trong Assets/Hamster/Scripts/States/DebugMenu.cs, hãy ghi đè LogStringsAndCrashNow() như sau:
    void LogStringsAndCrashNow()
    {
        Crashlytics.Log($"This is the first of two descriptive strings in {nameof(LogStringsAndCrashNow)}");
        const bool RUN_OPTIONAL_PATH = false;
        if(RUN_OPTIONAL_PATH)
        {
            Crashlytics.Log(" As it stands, this log should not appear in your records because it will never be called.");
        }
        else
        {
            Crashlytics.Log(" A log that will simply inform you which path of logic was taken. Akin to print debugging.");
        }
        Crashlytics.Log($"This is the second of two descriptive strings in {nameof(LogStringsAndCrashNow)}");
        TestCrash();
    }
    
  2. Xây dựng ứng dụng của bạn.
  3. (Chỉ dành cho Android) Tải các biểu tượng của bạn lên bằng cách chạy lệnh CLI Firebase sau:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Nhấn vào nút Log Strings and Crash Now (Ghi nhật ký chuỗi và sự cố ngay) rồi khởi động lại ứng dụng.
  5. Quay lại trang tổng quan của Crashlytics rồi nhấp vào vấn đề mới nhất trong bảng Vấn đề. Một lần nữa, bạn sẽ thấy nội dung tương tự như các vấn đề trước đó.
    7aabe103b8589cc7.pngs
  6. Tuy nhiên, nếu nhấp vào thẻ Nhật ký trong mục Tóm tắt sự kiện, bạn sẽ thấy một giao diện như sau:
    4e27aa407b7571cf.png.

10. Ghi và ghi đè một khoá tuỳ chỉnh

Giả sử bạn muốn hiểu rõ hơn về sự cố tương ứng với các biến được đặt thành một số ít giá trị hoặc cấu hình. Tốt nhất bạn nên có thể lọc dựa trên sự kết hợp của các biến và giá trị có thể có mà bạn đang xem xét tại một thời điểm bất kỳ.

Ngoài việc ghi nhật ký các chuỗi tuỳ ý, Crashlytics cung cấp một hình thức gỡ lỗi khác khi bạn nên biết trạng thái chính xác của chương trình khi chương trình gặp sự cố: khoá tuỳ chỉnh.

Đây là các cặp khoá-giá trị mà bạn có thể đặt cho một phiên. Không giống như các nhật ký tích luỹ và chỉ mang tính chất bổ sung, bạn có thể ghi đè các khoá để chỉ phản ánh trạng thái gần đây nhất của một biến hoặc điều kiện.

Ngoài việc giúp bạn lập sổ cái cho trạng thái được ghi lại gần đây nhất của chương trình, các khoá này còn có thể được dùng làm bộ lọc hữu ích cho các vấn đề trên Crashlytics.

  1. Trong Assets/Hamster/Scripts/States/DebugMenu.cs, hãy ghi đè SetAndOverwriteCustomKeyThenCrash() như sau:
    void SetAndOverwriteCustomKeyThenCrash()
    {
        const string CURRENT_TIME_KEY = "Current Time";
        System.TimeSpan currentTime = System.DateTime.Now.TimeOfDay;
        Crashlytics.SetCustomKey(
            CURRENT_TIME_KEY,
            DayDivision.GetPartOfDay(currentTime).ToString() // Values must be strings
            );
    
        // Time Passes
        currentTime += DayDivision.DURATION_THAT_ENSURES_PHASE_CHANGE;
    
        Crashlytics.SetCustomKey(
            CURRENT_TIME_KEY,
            DayDivision.GetPartOfDay(currentTime).ToString()
            );
        TestCrash();
    }
    
  2. Xây dựng ứng dụng của bạn.
  3. (Chỉ dành cho Android) Tải các biểu tượng của bạn lên bằng cách chạy lệnh CLI Firebase sau:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Nhấn vào nút Set Custom Key and Crash (Đặt khoá tuỳ chỉnh và sự cố) rồi khởi động lại ứng dụng.
  5. Quay lại trang tổng quan của Crashlytics rồi nhấp vào vấn đề mới nhất trong bảng Vấn đề. Một lần nữa, bạn sẽ thấy nội dung tương tự như các vấn đề trước đó.
  6. Tuy nhiên, lần này hãy nhấp vào thẻ Khoá trong mục Tóm tắt sự kiện để bạn có thể xem giá trị của các khoá, bao gồm cả Current Time:
    7dbe1eb00566af98.pngS

Tại sao bạn nên sử dụng khoá tuỳ chỉnh thay vì nhật ký tuỳ chỉnh?

  • Nhật ký rất hữu ích trong việc lưu trữ dữ liệu tuần tự, nhưng các khoá tuỳ chỉnh sẽ hoạt động hiệu quả hơn nếu bạn chỉ muốn giá trị gần đây nhất.
  • Trong bảng điều khiển của Firebase, bạn có thể dễ dàng lọc vấn đề theo giá trị của các khoá trong hộp tìm kiếm trên bảng Vấn đề.

Tuy nhiên, tương tự như nhật ký, khoá tuỳ chỉnh cũng có giới hạn. Crashlytics hỗ trợ tối đa 64 cặp khoá-giá trị. Sau khi bạn đạt đến ngưỡng này, các giá trị khác sẽ không được lưu. Mỗi cặp khoá-giá trị có thể có kích thước tối đa 1 KB.

11. (Chỉ dành cho Android) Dùng nhật ký và khoá tuỳ chỉnh để tìm hiểu và chẩn đoán lỗi ANR

Một trong những loại vấn đề khó gỡ nhất cho nhà phát triển Android là lỗi Ứng dụng không phản hồi (ANR). Lỗi ANR xảy ra khi ứng dụng không phản hồi thông tin đầu vào trong hơn 5 giây. Nếu vấn đề này xảy ra thì có nghĩa là ứng dụng bị treo hoặc hoạt động rất chậm. Người dùng sẽ thấy một hộp thoại và họ có thể chọn xem có "Chờ" hay không hoặc "Đóng ứng dụng".

ANR là trải nghiệm người dùng kém và (như đã đề cập trong đường liên kết về lỗi ANR ở trên) có thể ảnh hưởng đến khả năng người dùng tìm thấy ứng dụng của bạn trên Cửa hàng Google Play. Do độ phức tạp của các lỗi này và thường xảy ra do mã đa luồng có hành vi rất khác nhau trên nhiều mẫu điện thoại, nên việc tái tạo lỗi ANR trong khi gỡ lỗi thường rất khó khăn (nếu không phải là gần như không thể). Do đó, tiếp cận chúng theo cách phân tích và suy diễn thường là cách tiếp cận tốt nhất.

Trong phương thức này, chúng tôi sẽ sử dụng tổ hợp Crashlytics.LogException, Crashlytics.LogCrashlytics.SetCustomKey để bổ sung cho tính năng tự động ghi nhật ký vấn đề cũng như để cung cấp thêm thông tin cho chúng tôi.

  1. Trong Assets/Hamster/Scripts/States/DebugMenu.cs, hãy ghi đè SetLogsAndKeysBeforeANR() như sau:
    void SetLogsAndKeysBeforeANR()
    {
        System.Action<string,long> WaitAndRecord =
        (string methodName, long targetCallLength)=>
        {
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            const string CURRENT_FUNCTION = "Current Async Function";
    
            // Initialize key and start timing
            Crashlytics.SetCustomKey(CURRENT_FUNCTION, methodName);
            stopWatch.Start();
    
            // The actual (simulated) work being timed.
            BusyWaitSimulator.WaitOnSimulatedBlockingWork(targetCallLength);
    
            // Stop timing
            stopWatch.Stop();
    
            if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.EXTREME_DURATION_MILLIS)
            {
              Crashlytics.Log($"'{methodName}' is long enough to cause an ANR.");
            }
            else if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.SEVERE_DURATION_MILLIS)
            {
              Crashlytics.Log($"'{methodName}' is long enough it may cause an ANR");
            }
        };
    
        WaitAndRecord("DoSafeWork",1000L);
        WaitAndRecord("DoSevereWork",BusyWaitSimulator.SEVERE_DURATION_MILLIS);
        WaitAndRecord("DoExtremeWork",2*BusyWaitSimulator.EXTREME_DURATION_MILLIS);
    }
    
  2. Xây dựng ứng dụng của bạn.
  3. Tải các biểu tượng lên bằng cách chạy lệnh CLI của Firebase sau:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Nhấn vào nút có nhãn Set Logs And Key (Đặt nhật ký và khoá) → ANR (ANR) rồi khởi động lại ứng dụng.
  5. Quay lại trang tổng quan của Crashlytics, sau đó nhấp vào vấn đề mới trong bảng Vấn đề để xem Tóm tắt sự kiện. Nếu lệnh gọi diễn ra đúng cách, bạn sẽ thấy như sau:
    876c3cff7037bd07.pngs

    Như bạn có thể thấy, Firebase đã xác định chính xác trạng thái chờ đợi trên luồng là lý do chính khiến ứng dụng của bạn kích hoạt lỗi ANR.
  6. Nếu xem nhật ký trong thẻ Nhật ký của mục Tóm tắt sự kiện, bạn sẽ thấy phương thức cuối cùng được ghi lại là hoàn tất là DoSevereWork.
    5a4bec1cf06f6984.png.

    Ngược lại, phương thức cuối cùng được liệt kê là bắt đầu là DoExtremeWork, cho biết rằng lỗi ANR đã xảy ra trong phương thức này và trò chơi đã đóng trước khi có thể ghi nhật ký DoExtremeWork.

    89d86d5f598ecf3a.png.

Tại sao lại làm như vậy?

  • Việc tái tạo lỗi ANR là điều vô cùng khó khăn, vì vậy, việc có được nhiều thông tin phong phú về vùng mã và các chỉ số đóng vai trò cực kỳ quan trọng trong việc tìm ra lỗi này theo cách suy luận.
  • Nhờ thông tin được lưu trữ trong các khoá tuỳ chỉnh, giờ đây, bạn đã biết được luồng không đồng bộ nào mất nhiều thời gian nhất để chạy và luồng nào có nguy cơ kích hoạt lỗi ANR. Loại dữ liệu số và logic có liên quan này sẽ cho bạn biết vị trí nào trong mã của bạn là cần thiết nhất để tối ưu hoá.

12. Xen kẽ các sự kiện Analytics để làm phong phú báo cáo hơn nữa

Bạn cũng có thể gọi các phương thức sau từ Trình đơn gỡ lỗi, nhưng thay vì tự tạo ra vấn đề, các phương thức này sử dụng Google Analytics như một nguồn thông tin khác để hiểu rõ hơn về hoạt động của trò chơi.

Không giống như các phương thức khác mà bạn đã viết trong lớp học lập trình này, bạn nên sử dụng kết hợp các phương thức này với các phương thức khác. Gọi các phương thức này (bằng cách nhấn nút tương ứng trong Trình đơn gỡ lỗi) theo bất kỳ thứ tự tuỳ ý nào bạn muốn trước khi chạy một trong các phương thức khác. Sau đó, khi kiểm tra thông tin trong vấn đề cụ thể trên Crashlytics, bạn sẽ thấy một nhật ký theo thứ tự gồm các sự kiện Analytics. Bạn có thể dùng dữ liệu này trong trò chơi để hiểu rõ hơn về sự kết hợp giữa quy trình hoạt động của chương trình hoặc hoạt động đầu vào của người dùng, tuỳ thuộc vào cách bạn đo lường ứng dụng.

  1. Trong Assets/Hamster/Scripts/States/DebugMenu.cs, hãy ghi đè các phương thức triển khai hiện có của các phương thức sau:
    public void LogProgressEventWithStringLiterals()
    {
          Firebase.Analytics.FirebaseAnalytics.LogEvent("progress", "percent", 0.4f);
    }
    
    public void LogIntScoreWithBuiltInEventAndParams()
    {
          Firebase.Analytics.FirebaseAnalytics
            .LogEvent(
              Firebase.Analytics.FirebaseAnalytics.EventPostScore,
              Firebase.Analytics.FirebaseAnalytics.ParameterScore,
              42
            );
    }
    
  2. Tạo và triển khai trò chơi, sau đó nhập Trình đơn gỡ lỗi.
  3. (Chỉ dành cho Android) Tải các biểu tượng của bạn lên bằng cách chạy lệnh CLI Firebase sau:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Nhấn ít nhất một trong các nút sau một hoặc nhiều lần để gọi các chức năng trên:
    • Ghi nhật ký sự kiện chuỗi
    • Ghi nhật ký sự kiện
  5. Nhấn vào nút Crash Now (Sự cố ngay).
  6. Khởi động lại trò chơi để tải sự kiện sự cố lên Firebase.
  7. Khi bạn ghi lại nhiều trình tự sự kiện Analytics tuỳ ý, rồi thiết lập trò chơi của bạn tạo một sự kiện mà Crashlytics tạo báo cáo (như bạn vừa có), chúng sẽ được thêm vào thẻ Nhật ký của Tóm tắt sự kiện của Crashlytics như sau:
    d3b16d78f76bfb04.pngs

13. Từ giờ trở đi

Nhờ đó, bạn sẽ có cơ sở lý thuyết tốt hơn để bổ sung cho báo cáo sự cố được tạo tự động. Thông tin mới này cho phép bạn sử dụng trạng thái hiện tại, bản ghi sự kiện trong quá khứ và sự kiện hiện có trong Google Analytics để phân tích chính xác hơn trình tự và logic dẫn đến kết quả của sự kiện.

Nếu ứng dụng của bạn nhắm đến Android 11 (API cấp 30) trở lên, hãy cân nhắc việc kết hợp GWP-ASan, một tính năng trình phân bổ bộ nhớ gốc giúp gỡ lỗi các sự cố do lỗi bộ nhớ gốc gây ra, chẳng hạn như lỗi use-after-freeheap-buffer-overflow. Để tận dụng tính năng gỡ lỗi này, hãy bật GWP-ASan một cách rõ ràng.

Các bước tiếp theo

Tiếp tục tham gia lớp học lập trình Đo lường trò chơi Unity bằng Cấu hình từ xa, nơi bạn sẽ tìm hiểu cách sử dụng Cấu hình từ xa và Thử nghiệm A/B trong Unity.