1. מבוא
ב-codelab הזה תלמדו איך להשתמש בתכונות מתקדמות של Crashlytics שיעזרו לכם לקבל תמונה ברורה יותר של הקריסות ושל הנסיבות שגרמו להן.
תצטרכו להוסיף פונקציונליות חדשה למשחק לדוגמה, MechaHamster: Level Up with Firebase Edition. משחק הדוגמה הזה הוא גרסה חדשה של משחק Firebase הקלאסי MechaHamster. בגרסה הזו הוסרה רוב הפונקציונליות המובנית של Firebase, כדי שתוכלו להטמיע במקומה שימושים חדשים ב-Firebase.
תוסיפו תפריט ניפוי באגים למשחק. תפריט הניפוי באגים הזה קורא לשיטות שתיצרו, ומאפשר לכם להשתמש בפונקציות השונות של Crashlytics. במאמר הזה נסביר איך להוסיף הערות לדוחות הקריסה האוטומטיים באמצעות מפתחות מותאמים אישית, יומנים מותאמים אישית, שגיאות לא קריטיות ועוד.
אחרי שתסיימו לפתח את המשחק, תוכלו להשתמש בתפריט ניפוי הבאגים ולבדוק את התוצאות כדי להבין את התצוגה הייחודית שהן מספקות לגבי אופן הפעלת המשחק בסביבת ייצור.
מה תלמדו
- סוגי השגיאות ש-Crashlytics מזהה באופן אוטומטי.
- שגיאות נוספות שאפשר לתעד בכוונה.
- איך מוסיפים מידע לשגיאות האלה כדי שיהיה קל יותר להבין אותן.
מה צריך להכין
- Unity (גרסה מומלצת מינימלית 2019 ואילך) עם אחת מהאפשרויות הבאות או שתיהן:
- תמיכה בגרסאות Build של iOS
- תמיכה ב-Build של Android
- (ל-Android בלבד) Firebase CLI (משמש להעלאת סמלים לדוחות קריסה)
- פועלים לפי ההוראות להתקנת Firebase CLI.
אם כבר התקנתם את ה-CLI, חשוב לוודא שהגרסה שלו עדכנית.
- פועלים לפי ההוראות להתקנת Firebase CLI.
2. הגדרת סביבת הפיתוח
בקטעים הבאים מוסבר איך להוריד את הקוד של Level Up with Firebase ולפתוח אותו ב-Unity.
שימו לב: משחק הדוגמה Level Up with Firebase משמש כמה מדריכי Codelab אחרים של Firebase + Unity, כך שאולי כבר השלמתם את המשימות שבקטע הזה. אם כן, אפשר לעבור ישירות לשלב האחרון בדף הזה: 'הוספת Firebase SDKs for Unity'.
הורדת הקוד
משכפלים משורת הפקודה את מאגר GitHub של ה-codelab הזה:
git clone https://github.com/firebase/level-up-with-firebase.git
לחלופין, אם לא התקנתם את git, אתם יכולים להוריד את המאגר כקובץ ZIP.
פותחים את Level Up with Firebase בכלי לעריכת Unity
- מפעילים את Unity Hub ובכרטיסייה Projects לוחצים על החץ לתפריט הנפתח לצד Open.
- לוחצים על הוספת פרויקט מדיסק.
- עוברים לספרייה שמכילה את הקוד ולוחצים על אישור.
- אם תתבקשו, תצטרכו לבחור גרסה של Unity Editor שבה תרצו להשתמש ואת פלטפורמת היעד (Android או iOS).
- לוחצים על שם הפרויקט, level-up-with-firebase, והפרויקט ייפתח בכלי לעריכה של Unity.
- אם העורך לא נפתח אוטומטית, פותחים את
MainGameScene
ב-Assets > Hamster בכרטיסייה Project של Unity Editor.
מידע נוסף על התקנה ושימוש ב-Unity זמין במאמר עבודה ב-Unity.
3. הוספת Firebase לפרויקט ב-Unity
יצירת פרויקט Firebase
- נכנסים למסוף Firebase באמצעות חשבון Google.
- לוחצים על הלחצן כדי ליצור פרויקט חדש, ואז מזינים שם לפרויקט (לדוגמה,
Mechahamster Codelab
).
- לוחצים על המשך.
- אם מוצגת בקשה לעשות זאת, קוראים ומאשרים את התנאים של Firebase, ואז לוחצים על המשך.
- (אופציונלי) מפעילים את העזרה מבוססת-AI במסוף Firebase (שנקראת Gemini ב-Firebase).
- כדי להשתמש במוצרי Firebase בצורה אופטימלית, צריך להשתמש ב-Google Analytics. לכן, חשוב להשאיר את המתג במצב מופעל באפשרות של Google Analytics. פועלים לפי ההוראות במסך כדי להגדיר את Google Analytics.
- לוחצים על יצירת פרויקט, מחכים שהפרויקט יוקצה ולוחצים על המשך.
רישום האפליקציה ב-Firebase
- עדיין במסוף Firebase, במרכז דף סקירת הפרויקט, לוחצים על הסמל של Unity כדי להפעיל את תהליך ההגדרה. אם כבר הוספתם אפליקציה לפרויקט Firebase, לוחצים על הוספת אפליקציה כדי להציג את אפשרויות הפלטפורמה.
- בוחרים לרשום גם את יעדי ה-build של Apple (iOS) וגם את יעדי ה-build של Android.
- מזינים את המזהים הספציפיים לפלטפורמה של הפרויקט ב-Unity. ב-Codelab הזה, מזינים את הפרטים הבאים:
- ב-Apple (iOS): מזינים
com.google.firebase.level-up
בשדה מזהה חבילה ב-iOS. - ב-Android: מזינים
com.google.firebase.level_up
בשדה שם החבילה ל-Android.
- ב-Apple (iOS): מזינים
- (אופציונלי) מזינים את הכינויים הספציפיים לפלטפורמה של פרויקט Unity.
- לוחצים על Register app (רישום האפליקציה) ועוברים לקטע Download config file (הורדת קובץ התצורה).
הוספת קובצי הגדרות של Firebase
אחרי שלוחצים על Register app (רישום האפליקציה), תתבקשו להוריד שני קובצי הגדרה (קובץ הגדרה אחד לכל יעד בנייה). כדי להתחבר ל-Firebase, פרויקט Unity צריך את המטא-נתונים של Firebase בקבצים האלה.
- מורידים את שני קובצי התצורה הזמינים:
- ב-Apple (iOS): מורידים את הקובץ GoogleService-Info.plist.
- ב-Android: מורידים את הקובץ google-services.json.
- פותחים את החלון Project (פרויקט) של הפרויקט ב-Unity ומעבירים את שני קובצי התצורה לתיקייה Assets (נכסים).
- חוזרים למסוף Firebase, בתהליך ההגדרה, לוחצים על הבא וממשיכים להוספת Firebase SDKs for Unity.
הוספת Firebase SDKs for Unity
- לוחצים על הורדת Firebase Unity SDK במסוף Firebase.
- פותחים את ה-SDK במקום נוח.
- בפרויקט הפתוח ב-Unity, עוברים אל Assets (נכסים) > Import Package (ייבוא חבילה) > Custom Package (חבילה מותאמת אישית).
- בתיבת הדו-שיח Import package (ייבוא חבילה), עוברים אל הספרייה שמכילה את ה-SDK שלא נפרס, בוחרים באפשרות
FirebaseAnalytics.unitypackage
ולוחצים על Open (פתיחה). - בתיבת הדו-שיח Import Unity Package (ייבוא חבילת Unity) שמופיעה, לוחצים על Import (ייבוא).
- חוזרים על השלבים הקודמים כדי לייבא את
FirebaseCrashlytics.unitypackage
. - חוזרים למסוף Firebase ובתהליך ההגדרה לוחצים על הבא.
מידע נוסף על הוספת ערכות Firebase SDK לפרויקטים ב-Unity זמין במאמר אפשרויות נוספות להתקנה ב-Unity.
4. הגדרה של Crashlytics בפרויקט ב-Unity
כדי להשתמש ב-Crashlytics בפרויקטים של Unity, צריך לבצע עוד כמה שלבי הגדרה. כמובן שצריך להפעיל את ה-SDK. בנוסף, תצטרכו להעלות את הסמלים כדי שתוכלו לראות את עקבות מחסנית הזיכרון עם הסמלים במסוף Firebase, ותצטרכו לגרום לקריסה של האפליקציה כדי לוודא ש-Firebase מקבל את אירועי הקריסה.
אתחול ה-Crashlytics SDK
- ב-
Assets/Hamster/Scripts/MainGame.cs
, מוסיפים את ההצהרות הבאות שלusing
: המודול הראשון מאפשר לכם להשתמש בשיטות מ-Crashlytics SDK, והמודול השני מכיל כמה הרחבות ל-C# Tasks API. הקוד הבא לא יפעל בלי שני המשפטים bothusing Firebase.Crashlytics; using Firebase.Extensions;
using
. - עדיין ב-
MainGame.cs
, מוסיפים את האתחול של Firebase לשיטה הקיימתStart()
על ידי קריאה ל-InitializeFirebaseAndStartGame()
:void Start() { Screen.SetResolution(Screen.width / 2, Screen.height / 2, true); InitializeFirebaseAndStartGame(); }
- שוב, ב-
MainGame.cs
, מאתרים אתInitializeFirebaseAndStartGame()
, מגדירים משתנה של אפליקציה ואז מחליפים את ההטמעה של השיטה באופן הבא: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"); } }); }
הצבת לוגיקת האתחול כאן מונעת אינטראקציה של השחקן לפני שהתלות ב-Firebase מאותחלת.
היתרונות וההשפעות של דיווח על חריגות שלא טופלו כחמורות מוסברים בשאלות הנפוצות בנושא Crashlytics.
יצירת הפרויקט והעלאת סמלים
השלבים ליצירה ולהעלאה של סמלים שונים באפליקציות ל-iOS ולאפליקציות ל-Android.
iOS+ (פלטפורמת אפל)
- בתיבת הדו-שיח Build Settings (הגדרות בנייה), מייצאים את הפרויקט לסביבת עבודה של Xcode.
- מבצעים build לאפליקציה.
בפלטפורמות של Apple, התוסף Firebase Unity Editor מגדיר באופן אוטומטי את פרויקט Xcode כדי ליצור ולהעלות קובץ סמלים שתואם ל-Crashlytics לשרתי Firebase עבור כל build. המידע הזה על הסמלים נדרש כדי לראות דוחות על קריסות עם סימבולים בלוח הבקרה של Crashlytics.
Android
- (רק במהלך ההגדרה הראשונית, לא לכל בנייה) מגדירים את הבנייה:
- יוצרים תיקייה חדשה בשם Builds בתיקיית הבסיס של הפרויקט (כלומר, באותה רמה כמו התיקייה Assets), ואז יוצרים תיקיית משנה בשם Android.
- בקטע File (קובץ) > Build Settings (הגדרות בנייה) > Player Settings (הגדרות הפעלה) > Configuration (הגדרה), מגדירים את Scripting Backend (קצה עורפי של סקריפטים) ל-IL2CPP.
- בדרך כלל, שימוש ב-IL2CPP מוביל ליצירת קובצי build קטנים יותר עם ביצועים טובים יותר.
- IL2CPP היא גם האפשרות הזמינה היחידה ב-iOS, ובחירה בה כאן מאפשרת לשתי הפלטפורמות להיות שוות יותר ולהפוך את ניפוי הבאגים בין השתיים (אם בוחרים לבנות את שתיהן) לפשוט יותר.
- מבצעים Build לאפליקציה. בקובץ > הגדרות Build, משלימים את הפעולות הבאות:
- מוודאים שתיבת הסימון Create symbols.zip מסומנת (או אם מוצג תפריט נפתח, בוחרים באפשרות Debugging).
- יוצרים את ה-APK ישירות מ-Unity Editor לתוך תיקיית המשנה Builds/Android שיצרתם.
- אחרי שה-build מסתיים, צריך ליצור קובץ סמלים שתואם ל-Crashlytics ולהעלות אותו לשרתים של Firebase. המידע הזה על הסמלים נדרש כדי לראות דוחות קריסות עם סמלים של קריסות בספרייה נייטיבית בלוח הבקרה של Crashlytics.
מריצים את הפקודה הבאה של Firebase CLI כדי ליצור את קובץ הסמלים הזה ולהעלות אותו:firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
-
FIREBASE_APP_ID
: מזהה האפליקציה ל-Android ב-Firebase (לא שם החבילה). הערך הזה מופיע בקובץgoogle-services.json
שהורדתם קודם. זה הערךmobilesdk_app_id
.
דוגמה למזהה אפליקציה ב-Firebase ל-Android:1:567383003300:android:17104a2ced0c9b9b
-
PATH/TO/SYMBOLS
: הנתיב של קובץ הסמלים בפורמט ZIP שנוצר בספרייה Builds/Android כשה-build הסתיים (לדוגמה:Builds/Android/myapp-1.0-v100.symbols.zip
).
-
כדי לסיים את ההגדרה, צריך לגרום לקריסה של האפליקציה במהלך הבדיקה
כדי לסיים את ההגדרה של Crashlytics ולראות נתונים ראשוניים בלוח הבקרה של Crashlytics במסוף Firebase, צריך לגרום לקריסת בדיקה.
- ב-MainGameScene מוצאים את EmptyObject
GameObject
בעורך Hierarchy, מוסיפים לו את הסקריפט הבא ושומרים את הסצנה. הסקריפט הזה יגרום לקריסת בדיקה כמה שניות אחרי שתפעילו את האפליקציה.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"); } } }
- בונים את האפליקציה ומעלים את פרטי הסמלים אחרי שהבנייה מסתיימת.
- iOS: הפלאגין Firebase Unity Editor מגדיר אוטומטית את פרויקט Xcode להעלאת קובץ הסמלים.
- Android: מריצים את הפקודה
crashlytics:symbols:upload
של Firebase CLI כדי להעלות את קובץ הסמלים.
- מריצים את האפליקציה. כשהאפליקציה פועלת, צופים ביומן המכשיר ומחכים שהחריגה תופעל מ-
CrashlyticsTester
.- iOS: הצגת היומנים בחלונית התחתונה של Xcode.
- Android: כדי להציג את היומנים, מריצים את הפקודה הבאה במסוף:
adb logcat
.
- אפשר לעבור אל לוח הבקרה של Crashlytics כדי לראות את החריגה. היא תופיע בטבלה בעיות בתחתית מרכז הבקרה. בהמשך ה-codelab נסביר איך לעיין בדוחות האלה.
- אחרי שמוודאים שהאירוע הועלה ל-Crashlytics, בוחרים את EmptyObject
GameObject
שאליו צירפתם אותו, מסירים רק את הרכיבCrashlyticsTester
ואז שומרים את הסצנה כדי לשחזר אותה למצב המקורי.
5. הפעלה והסבר על תפריט ניפוי הבאגים
עד עכשיו, הוספתם את Crashlytics לפרויקט Unity, סיימתם את ההגדרה ואישרתם ש-Crashlytics SDK מעלה אירועים ל-Firebase. עכשיו תיצרו תפריט בפרויקט Unity כדי להדגים איך להשתמש בפונקציונליות מתקדמת יותר של Crashlytics במשחק. בפרויקט Unity Level Up with Firebase כבר יש תפריט ניפוי באגים מוסתר, ואתם תצטרכו להפוך אותו לגלוי ולכתוב את הפונקציונליות שלו.
הפעלת תפריט ניפוי הבאגים
הלחצן לגישה לתפריט הניפוי קיים בפרויקט Unity, אבל הוא לא מופעל כרגע. כדי לגשת ללחצן מ-MainMenu
prefab, צריך להפעיל אותו:
- ב-Unity Editor, פותחים את ה-prefab שנקרא
MainMenu
. - בהיררכיית ה-prefab, מחפשים את אובייקט המשנה המושבת שנקרא
DebugMenuButton
ובוחרים אותו. - מסמנים את התיבה בפינה הימנית העליונה, משמאל לשדה הטקסט שמכיל את
DebugMenuButton
, כדי להפעיל אתDebugMenuButton
. - שומרים את ה-prefab.
- מריצים את המשחק בעורך או במכשיר. עכשיו אמורה להיות לכם גישה לתפריט.
תצוגה מקדימה והסבר על גופי השיטות בתפריט ניפוי הבאגים
בהמשך ה-codelab הזה, תכתבו גופי שיטות לכמה שיטות מוגדרות מראש של Crashlytics לניפוי באגים. לעומת זאת, בפרויקט Unity Level Up with Firebase, המידע על ה-methods מוגדר ב-DebugMenu.cs
ונקרא ממנו.
חלק מהשיטות האלה יקראו לשיטות של Crashlytics ויציגו שגיאות, אבל היכולת של Crashlytics לזהות את השגיאות האלה לא תלויה בקריאה לשיטות האלה קודם. במקום זאת, דוחות הקריסה שנוצרים מתיעוד אוטומטי של שגיאות ישופרו על ידי המידע שנוסף בשיטות האלה.
פותחים את DebugMenu.cs
ומחפשים את השיטות הבאות:
שיטות ליצירת בעיות ב-Crashlytics ולהוספת הערות לגביהן:
CrashNow
LogNonfatalError
LogStringsAndCrashNow
SetAndOverwriteCustomKeyThenCrash
SetLogsAndKeysBeforeANR
שיטות לתיעוד אירועים ב-Analytics כדי לעזור בניפוי באגים:
LogProgressEventWithStringLiterals
LogIntScoreWithBuiltInEventAndParams
בשלבים הבאים של ה-codelab הזה, תטמיעו את השיטות האלה ותלמדו איך הן עוזרות לטפל במצבים ספציפיים שיכולים להתרחש בפיתוח משחקים.
6. איך מוודאים שדוחות קריסה יישלחו במהלך הפיתוח
לפני שמתחילים להטמיע את שיטות ניפוי הבאגים האלה ולראות איך הן משפיעות על דוחות הקריסה, חשוב להבין איך אירועים מדווחים ל-Crashlytics.
בפרויקטים של Unity, אירועי קריסה וחריגים במשחק נכתבים מיד לדיסק. אם יש חריגים שלא נתפסו ולא גורמים לקריסת המשחק (לדוגמה, חריגים שלא נתפסו ב-C# בלוגיקה של המשחק), אפשר להגדיר את Crashlytics SDK כך שידווח עליהם כאירועים קריטיים. לשם כך, צריך להגדיר את המאפיין Crashlytics.ReportUncaughtExceptionsAsFatal
לערך true
במקום שבו מאתחלים את Crashlytics בפרויקט Unity. האירועים האלה מדווחים ל-Crashlytics בזמן אמת, בלי שמשתמש הקצה יצטרך להפעיל מחדש את המשחק. שימו לב שקריסות מקוריות תמיד מדווחות כאירועים קריטיים ונשלחות כשהמשתמש הסופי מפעיל מחדש את המשחק.
בנוסף, חשוב לשים לב להבדלים הקטנים – אך המשמעותיים – הבאים בין האופן שבו סביבות זמן הריצה השונות שולחות מידע מ-Crashlytics אל Firebase:
סימולטור iOS:
- המידע של Crashlytics מדווח רק אם מנתקים את Xcode מהסימולטור. אם Xcode מצורף, הוא מאתר את השגיאות במעלה הזרם ומונע את העברת המידע.
מכשירים פיזיים לנייד (Android ו-iOS):
- ספציפי ל-Android: דוחות על מקרי ANR מתקבלים רק ב-Android 11 ואילך. דוחות על מקרי ANR ואירועים לא חמורים מתקבלים בהפעלה הבאה.
Unity Editor:
- המידע מ-Crashlytics מהעורך במצב הפעלה או בגרסה עצמאית לא נרשם ולא מועלה ל-Firebase. בנוסף, תהליך העבודה לפיתוח אפליקציות ל-Desktop ב-Firebase לא תומך ב-Crashlytics.
ב-CrashNow()
אפשר לבדוק את קריסת המשחק בלחיצת כפתור
אחרי שמגדירים את Crashlytics במשחק, ה-SDK של Crashlytics מתעד באופן אוטומטי קריסות וחריגים שלא נתפסו, ומעלה אותם ל-Firebase לצורך ניתוח. הדוחות מוצגים בלוח הבקרה של Crashlytics במסוף Firebase.
- כדי להראות שזה אכן אוטומטי: פותחים את
DebugMenu.cs
, ואז מחליפים את המתודהCrashNow()
באופן הבא:void CrashNow() { TestCrash(); }
- יוצרים את האפליקציה.
- (Android בלבד) מעלים את הסמלים באמצעות הפעלת הפקודה הבאה ב-Firebase CLI:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- מקישים על הכפתור Crash Now (קריסה עכשיו) וממשיכים לשלב הבא ב-Codelab הזה כדי לראות איך לצפות בדוח הקריסה ולפרש אותו.
7. הסבר על דוחות בעיות במסוף Firebase
כשמעיינים בדוחות קריסה, יש עוד כמה דברים שחשוב לדעת כדי להפיק מהם את המרב. בכל אחת מהשיטות שתכתבו יוסבר איך להוסיף סוגים שונים של מידע לדוחות של Crashlytics.
- מקישים על הלחצן Crash Now (קריסה עכשיו) ומפעילים מחדש את האפליקציה.
- עוברים אל מרכז הבקרה של Crashlytics. גוללים למטה לטבלה Issues בתחתית לוח הבקרה, שבה Crashlytics מקבץ אירועים עם אותה סיבת שורש ל'בעיות'.
- לוחצים על הבעיה החדשה שמופיעה בטבלה בעיות. כך מוצג סיכום האירועים לגבי כל אירוע בנפרד שנשלח ל-Firebase.
התוצאה אמורה להיראות כמו בצילום המסך הבא. שימו לב איך סיכום האירוע כולל באופן בולט את מעקב המחסנית של הקריאה שהובילה לקריסה.
מטא-נתונים נוספים
כרטיסייה שימושית נוספת היא Unity Metadata (מטא-נתונים של Unity). בקטע הזה מפורטים מאפייני המכשיר שבו התרחש האירוע, כולל מאפיינים פיזיים, דגם/מפרט של ה-CPU וכל מיני מדדים של ה-GPU.
הנה דוגמה שבה המידע בכרטיסייה הזו יכול להיות שימושי:
נניח שהמשחק שלכם משתמש הרבה ב-shaders כדי להשיג מראה מסוים, אבל לא לכל הטלפונים יש יחידות GPU שיכולות לעבד את התכונה הזו. המידע בכרטיסייה Unity Metadata יכול לעזור לכם להבין טוב יותר אילו רכיבי חומרה כדאי לבדוק באפליקציה כשאתם מחליטים אילו תכונות להפעיל או להשבית באופן אוטומטי.
יכול להיות שבאג או קריסה אף פעם לא יקרו במכשיר שלכם, אבל בגלל המגוון העצום של מכשירי Android בשוק, כדאי להבין טוב יותר את ה"נקודות החמות" הספציפיות במכשירים של הקהל שלכם.
8. הקפצת הודעת שגיאה (throw), תפיסה (catch) ותיעוד (log) של חריגה
לעתים קרובות, בתור מפתחים, גם אם הקוד שלכם תופס ומטפל בצורה נכונה בחריגה בזמן ריצה, כדאי לציין שהיא התרחשה ובאילו נסיבות. אפשר להשתמש ב-Crashlytics.LogException
בדיוק למטרה הזו – שליחת אירוע חריג ל-Firebase כדי שתוכלו לנפות באגים בבעיה במסוף Firebase.
- ב-
Assets/Hamster/Scripts/States/DebugMenu.cs
, מוסיפים את ההצהרות הבאות להצהרותusing
:// Import Firebase using Firebase.Crashlytics;
- עדיין ב-
DebugMenu.cs
, מחליפים אתLogNonfatalError()
באופן הבא:void LogNonfatalError() { try { throw new System.Exception($"Test exception thrown in {nameof(LogNonfatalError)}"); } catch(System.Exception exception) { Crashlytics.LogException(exception); } }
- יוצרים את האפליקציה.
- (Android בלבד) מעלים את הסמלים באמצעות הפעלת הפקודה הבאה ב-Firebase CLI:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- מקישים על הלחצן Log Nonfatal Error ומפעילים מחדש את האפליקציה.
- עוברים אל מרכז הבקרה של Crashlytics, ורואים משהו דומה למה שראיתם בשלב האחרון של ה-codelab הזה.
- אבל הפעם, מגבילים את המסנן Event type ל-Non-fatals כדי לראות רק שגיאות לא קריטיות, כמו השגיאה שרשמתם ביומן.
9. רישום מחרוזות ביומן ב-Crashlytics כדי להבין טוב יותר את רצף הפעולות של ביצוע התוכנית
ניסיתם פעם להבין למה שורת קוד שמופעלת מכמה נתיבים, מאות פעמים אם לא אלפי פעמים בכל סשן, יכולה פתאום ליצור חריגה או לקרוס? יכול להיות שתרצו לעבור על הקוד בסביבת פיתוח משולבת (IDE) ולבדוק את הערכים מקרוב, אבל מה אם זה קורה רק אצל אחוז קטן מאוד מהמשתמשים? מה תעשו אם לא תצליחו לשחזר את הקריסה, לא משנה מה תנסו?
במקרים כאלה, הקשר יכול לעשות את כל ההבדל. עם Crashlytics.Log
, אתם יכולים לכתוב את ההקשר שאתם צריכים. אפשר לחשוב על ההודעות האלה כרמזים לעצמכם בעתיד לגבי מה שקורה.
אפשר להשתמש ביומנים במגוון דרכים, אבל בדרך כלל הם הכי שימושיים לתיעוד מצבים שבהם הסדר או היעדר של שיחות הם מידע חשוב ביותר.
- ב-
Assets/Hamster/Scripts/States/DebugMenu.cs
, מחליפים אתLogStringsAndCrashNow()
באופן הבא: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(); }
- יוצרים את האפליקציה.
- (Android בלבד) מעלים את הסמלים באמצעות הפעלת הפקודה הבאה ב-Firebase CLI:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- מקישים על הלחצן Log Strings and Crash Now (רישום מחרוזות ביומן וקריסה מיידית) ואז מפעילים מחדש את האפליקציה.
- חוזרים אל מרכז הבקרה של Crashlytics ולוחצים על הבעיה החדשה ביותר שמופיעה בטבלה Issues. שוב, אמורה להופיע בעיה דומה לבעיות הקודמות.
- עם זאת, אם לוחצים על הכרטיסייה יומנים בתוך סיכום אירועים, מוצג תצוגה כזו:
10. כתיבה של מפתח בהתאמה אישית או החלפה שלו
נניח שאתם רוצים להבין טוב יותר קריסה שמתאימה למשתנים שהוגדרו למספר קטן של ערכים או תצורות. יכול להיות שתרצו לסנן לפי שילוב המשתנים והערכים האפשריים שאתם בודקים בכל רגע נתון.
בנוסף לרישום מחרוזות שרירותיות, Crashlytics מציעה עוד סוג של ניפוי באגים שמועיל לדעת את המצב המדויק של התוכנית בזמן הקריסה: מפתחות בהתאמה אישית.
אלה צמדים של מפתח/ערך שאפשר להגדיר לסשן. בניגוד ליומנים שמצטברים ומוסיפים נתונים, אפשר לדרוס מפתחות כדי שישקפו רק את הסטטוס האחרון של משתנה או תנאי.
בנוסף להיותם ספר חשבונות של המצב האחרון שתועד בתוכנית, אפשר להשתמש במפתחות האלה כמסננים חזקים לבעיות ב-Crashlytics.
- ב-
Assets/Hamster/Scripts/States/DebugMenu.cs
, מחליפים אתSetAndOverwriteCustomKeyThenCrash()
באופן הבא: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(); }
- יוצרים את האפליקציה.
- (Android בלבד) מעלים את הסמלים באמצעות הפעלת הפקודה הבאה ב-Firebase CLI:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- מקישים על הלחצן Set Custom Key and Crash (הגדרת מפתח מותאם אישית וקריסה) ומפעילים מחדש את האפליקציה.
- חוזרים אל מרכז הבקרה של Crashlytics ולוחצים על הבעיה החדשה ביותר שמופיעה בטבלה Issues. שוב, אמורה להופיע בעיה דומה לבעיות הקודמות.
- הפעם, לוחצים על הכרטיסייה Keys (מפתחות) בEvent summary (סיכום האירוע) כדי לראות את הערך של המפתחות, כולל
Current Time
:
למה כדאי להשתמש במפתחות מותאמים אישית במקום ביומנים מותאמים אישית?
- קבצי יומן טובים לאחסון נתונים רציפים, אבל מפתחות בהתאמה אישית עדיפים אם רוצים רק את הערך העדכני ביותר.
- במסוף Firebase, אפשר לסנן בקלות בעיות לפי ערכי מפתחות בתיבת החיפוש של הטבלה Issues.
בדומה ליומנים, יש מגבלה על מספר המפתחות המותאמים אישית. ב-Crashlytics יש תמיכה ב-64 צמדי מפתח/ערך לכל היותר. אחרי שמגיעים לסף הזה, המערכת לא שומרת ערכים נוספים. כל צמד מפתח/ערך יכול להיות בגודל של עד 1KB.
11. (Android בלבד) שימוש במפתחות וביומנים מותאמים אישית כדי להבין ולנתח ANR
אחת מהבעיות שהכי קשה לנפות באנדרואיד היא השגיאה האפליקציה לא מגיבה (ANR). שגיאות ANR מתרחשות כשאפליקציה לא מגיבה לקלט במשך יותר מ-5 שניות. אם זה קורה, המשמעות היא שהאפליקציה קפאה או שהיא פועלת לאט מאוד. מוצגת למשתמשים תיבת דו-שיח שבה הם יכולים לבחור באפשרות 'המתנה' או 'סגירת האפליקציה'.
מקרי ANR פוגעים בחוויית המשתמש, וכמו שצוין בקישור למעלה בנושא ANR, הם יכולים להשפיע על יכולת הגילוי של האפליקציה בחנות Google Play. בגלל המורכבות שלהם, ובגלל שהם נגרמים לעיתים קרובות על ידי קוד מרובה-שרשורים עם התנהגות שונה מאוד בדגמי טלפון שונים, קשה מאוד לשחזר ANR במהלך ניפוי באגים, אם לא בלתי אפשרי. לכן, בדרך כלל הגישה הטובה ביותר היא ניתוח והסקת מסקנות.
בשיטה הזו נשתמש בשילוב של Crashlytics.LogException
, Crashlytics.Log
ו-Crashlytics.SetCustomKey
כדי להוסיף לרישום האוטומטי של הבעיות ולספק לנו מידע נוסף.
- ב-
Assets/Hamster/Scripts/States/DebugMenu.cs
, מחליפים אתSetLogsAndKeysBeforeANR()
באופן הבא: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); }
- יוצרים את האפליקציה.
- מעלים את הסמלים באמצעות הפקודה הבאה ב-Firebase CLI:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- מקישים על הלחצן Set Logs And Keys → ANR (הגדרת יומנים ומפתחות ← ANR) ומפעילים מחדש את האפליקציה.
- חוזרים אל לוח הבקרה של Crashlytics ולוחצים על הבעיה החדשה בטבלה Issues כדי לראות את Event summary. אם השיחה עברה בצורה תקינה, אמור להופיע משהו כזה:
כפי שאפשר לראות, Firebase זיהה את ההמתנה העמוסה ב-thread כסיבה העיקרית להפעלת ה-ANR באפליקציה. - אם בודקים את היומנים בכרטיסייה יומנים בסיכום האירועים, אפשר לראות שהשיטה האחרונה שתועדה כהשלמה היא
DoSevereWork
.
לעומת זאת, השיטה האחרונה שמופיעה כהתחלה היאDoExtremeWork
, מה שמצביע על כך שה-ANR התרחש במהלך השיטה הזו, והמשחק נסגר לפני שהצליח לרשום אתDoExtremeWork
.
מדוע לעשות זאת?
- קשה מאוד לשחזר ANR, ולכן חשוב מאוד לקבל מידע מפורט על אזור הקוד והמדדים כדי להסיק מה קרה.
- בעזרת המידע שמאוחסן במפתחות המותאמים אישית, אתם יכולים לדעת עכשיו איזה thread אסינכרוני לקח הכי הרבה זמן לרוץ, ואילו מהם היו בסכנה של הפעלת ANR. נתונים לוגיים ומספריים קשורים כאלה יראו לכם איפה בקוד הכי חשוב לבצע אופטימיזציה.
12. שילוב אירועים מ-Analytics כדי להעשיר את הדוחות
אפשר להפעיל את השיטות הבאות גם מתפריט ניפוי הבאגים, אבל במקום ליצור בעיות בעצמן, הן משתמשות ב-Google Analytics כמקור מידע נוסף כדי להבין טוב יותר את אופן הפעולה של המשחק.
בניגוד לשיטות האחרות שכתבת במעבדת הקוד הזו, כדאי להשתמש בשיטות האלה בשילוב עם השיטות האחרות. אפשר להפעיל את השיטות האלה (על ידי לחיצה על הלחצן המתאים בתפריט הניפוי באגים) בכל סדר שרוצים לפני שמפעילים שיטה אחרת. לאחר מכן, כשבודקים את המידע בבעיה הספציפית ב-Crashlytics, אפשר לראות יומן מסודר של אירועי Analytics. אפשר להשתמש בנתונים האלה במשחק כדי להבין טוב יותר שילוב של זרימת התוכנית או קלט משתמש, בהתאם לאופן שבו הטמעתם את האפליקציה.
- ב-
Assets/Hamster/Scripts/States/DebugMenu.cs
, מחליפים את ההטמעות הקיימות של השיטות הבאות: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 ); }
- יוצרים את המשחק ומפיצים אותו, ואז נכנסים אל תפריט ניפוי הבאגים.
- (Android בלבד) מעלים את הסמלים באמצעות הפעלת הפקודה הבאה ב-Firebase CLI:
firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
- כדי להפעיל את הפונקציות שלמעלה, לוחצים על אחד מהלחצנים הבאים פעם אחת או יותר:
- אירוע של מחרוזת ביומן
- Log Int Event
- לוחצים על הלחצן Crash Now (קריסה עכשיו).
- מפעילים מחדש את המשחק כדי שאירוע הקריסה יועלה ל-Firebase.
- כשמתעדים רצפים שונים של אירועים ב-Analytics ואז המשחק יוצר אירוע ש-Crashlytics יוצר ממנו דוח (כמו שקרה עכשיו), האירועים האלה מתווספים לכרטיסייה Logs בדוח Event Summary של Crashlytics, כמו בדוגמה הבאה:
13. מה יהיה בהמשך
עכשיו יש לכם בסיס תיאורטי טוב יותר להוספת מידע לדוחות הקריסה שנוצרים באופן אוטומטי. המידע החדש הזה מאפשר לכם להשתמש במצב הנוכחי, ברשומות של אירועים קודמים ובאירועים קיימים ב-Google Analytics כדי לפרק טוב יותר את רצף האירועים והלוגיקה שהובילו לתוצאה.
אם האפליקציה שלכם מטרגטת ל-Android 11 (רמת API 30) ומעלה, כדאי לשלב את GWP-ASan, תכונה של הקצאת זיכרון נייטיב שיכולה לעזור בניפוי באגים של קריסות שנגרמות משגיאות זיכרון נייטיב, כמו באגים מסוג use-after-free
ו-heap-buffer-overflow
. כדי להשתמש בתכונת הניפוי באגים הזו, צריך להפעיל במפורש את GWP-ASan.
השלבים הבאים
אפשר להמשיך אל ה-codelab בנושא הטמעה של הגדרת תצורה מרחוק במשחק Unity, שבו תלמדו איך להשתמש בהגדרת תצורה מרחוק וב-A/B Testing ב-Unity.