في الإصدار 16 من نظام التشغيل Android (المستوى 36 لواجهة برمجة التطبيقات) والإصدارات الأحدث، تتيح لك أداة ProfilingManager تسجيل
الملفات الشخصية تلقائيًا استجابةً لمشغّلات النظام، مثل أخطاء التطبيق لا
يستجيب (ANR) أو أعطال نفاد الذاكرة (OutOfMemoryError) أو أحداث
بدء تشغيل التطبيق. بما أنّه لا يمكن توقّع وقت حدوث العديد من هذه الأحداث
في الميدان، من غير العملي بدء التسجيل يدويًا مسبقًا. من خلال ميزة "إنشاء الملفات الشخصية استنادًا إلى المشغّلات"، يدير النظام عملية التسجيل ويقدّم الملف الشخصي الناتج إلى تطبيقك لتتمكّن من إجراء ما يلي:
- تصحيح أخطاء الثبات: يمكنك تشخيص أخطاء ANR غير المتوقّعة وتسرُّب الذاكرة.
- تحسين رحلات المستخدم الأساسية (CUJ): يمكنك تحليل المسارات، مثل بدء تشغيل التطبيق (
TRIGGER_TYPE_COLD_STARTوTRIGGER_TYPE_APP_FULLY_DRAWN). - فهم سلوك المستخدمين: يمكنك فحص الأحداث، مثل عمليات الخروج من التطبيق التي يبدأها المستخدمون.
للاطّلاع على القائمة الكاملة للمشغّلات المتاحة، يُرجى مراجعة ProfilingTrigger.
أنواع المشغّلات
تختلف المشغّلات في كيفية تسجيل النظام للملف الشخصي عند وقوع الحدث.
العوامل التي تستخدم التتبُّع في الخلفية
تحدث العديد من المشاكل، مثل أخطاء ANR، نتيجة لمشكلة سابقة. فبدء التتبُّع بعد رصد النظام لخطأ ANR لا يتيح رصد عملية الحظر التي تسبّبت في حدوثه. لتسجيل النشاط الذي يؤدي إلى الحدث، تحفظ العوامل التالية لقطة من تتبُّع الخلفية النشط للنظام. إذا لم يكن هناك تتبُّع في الخلفية قيد التشغيل عند وقوع الحدث، لن يتم جمع أي ملف شخصي:
TRIGGER_TYPE_ANR(مستوى واجهة برمجة التطبيقات 36)TRIGGER_TYPE_APP_FULLY_DRAWN(مستوى واجهة برمجة التطبيقات 36)TRIGGER_TYPE_APP_REQUEST_RUNNING_TRACE(مستوى واجهة برمجة التطبيقات 36.1)TRIGGER_TYPE_KILL_FORCE_STOP(مستوى واجهة برمجة التطبيقات 36.1)TRIGGER_TYPE_KILL_RECENTS(مستوى واجهة برمجة التطبيقات 36.1)TRIGGER_TYPE_KILL_TASK_MANAGER(مستوى واجهة برمجة التطبيقات 36.1)TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE(مستوى واجهة برمجة التطبيقات 37)
الإجراءات التي تبدأ عملية التقاط جديدة
لا تعتمد عوامل التفعيل التالية على التتبُّع في الخلفية. بدلاً من ذلك، يبدأ النظام في التقاط ملف شخصي جديد عند وقوع الحدث:
TRIGGER_TYPE_COLD_START(مستوى واجهة برمجة التطبيقات 37)TRIGGER_TYPE_OOM(مستوى واجهة برمجة التطبيقات 37)
العوامل المشغِّلة التي يختلف فيها سلوك التسجيل حسب القيمة الشاذة
بالنسبة إلى عوامل التشغيل التالية للقيم الشاذة، يعتمد نوع الملف الشخصي الذي تم تسجيله (حفظ لقطة من تتبُّع الخلفية النشط أو بدء تسجيل جديد) وسلوك تحديد المعدّل على القيمة الشاذة المحدّدة التي يرصدها النظام:
TRIGGER_TYPE_ANOMALY(مستوى واجهة برمجة التطبيقات 37)TRIGGER_TYPE_APP_COMPAT(مستوى واجهة برمجة التطبيقات 37)
إعداد مشغِّل
يوضّح الرمز التالي كيفية التسجيل في مشغّل TRIGGER_TYPE_APP_FULLY_DRAWN وضبط فترة تهدئة له.
Kotlin
@RequiresApi(Build.VERSION_CODES.BAKLAVA) fun recordWithTrigger() { val profilingManager = applicationContext.getSystemService(ProfilingManager::class.java) ?: return val triggers = ArrayList<ProfilingTrigger>() val triggerBuilder = ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN) .setRateLimitingPeriodHours(1) triggers.add(triggerBuilder.build()) val callbackExecutor: Executor = Executors.newSingleThreadExecutor() val resultCallback = Consumer<ProfilingResult> { profilingResult -> if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.resultFilePath ) setupProfileUploadWorker(profilingResult.resultFilePath) } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.errorCode + " errormsg=" + profilingResult.errorMessage ) } } profilingManager.registerForAllProfilingResults(callbackExecutor, resultCallback) profilingManager.addProfilingTriggers(triggers) Choreographer.getInstance().postFrameCallback { frameTimeNanos -> // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. reportFullyDrawn() } }
Java
public void recordWithTrigger() { ProfilingManager profilingManager = getApplicationContext().getSystemService( ProfilingManager.class); List<ProfilingTrigger> triggers = new ArrayList<>(); ProfilingTrigger.Builder triggerBuilder = new ProfilingTrigger.Builder( ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN); triggerBuilder.setRateLimitingPeriodHours(1); triggers.add(triggerBuilder.build()); Executor callbackExecutor = Executors.newSingleThreadExecutor(); Consumer<ProfilingResult> resultCallback = new Consumer<ProfilingResult>() { @Override public void accept(ProfilingResult profilingResult) { if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.getResultFilePath()); setupProfileUploadWorker(profilingResult.getResultFilePath()); } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.getErrorCode() + " errormsg=" + profilingResult.getErrorMessage()); } } }; profilingManager.registerForAllProfilingResults(callbackExecutor, resultCallback); profilingManager.addProfilingTriggers(triggers); Choreographer.getInstance().postFrameCallback((f) -> { // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. reportFullyDrawn(); }); }
ينفّذ الرمز الخطوات التالية:
- الحصول على المدير: لاسترداد خدمة
ProfilingManager - تحديد مشغّل: ينشئ
ProfilingTriggerلـTRIGGER_TYPE_APP_FULLY_DRAWN. يحدث هذا الحدث عندما يستدعي التطبيقreportFullyDrawn()أثناء بدء تشغيل بارد بدأه النشاط للإبلاغ عن أنه انتهى من بدء التشغيل وأنه تفاعلي. - ضبط فترة تهدئة لمشغّل: يطبّق هذا الإجراء فترة تهدئة مدتها ساعة واحدة على هذا
المشغّل المحدّد باستخدام
setRateLimitingPeriodHoursبالإضافة إلى محدِّد معدّل النظام. تمنع فترة الانتظار هذه التطبيق من تسجيل أكثر من ملف شخصي واحد لبدء التشغيل في الساعة. - تسجيل المستمع: يستدعي
registerForAllProfilingResultsلتحديد دالة الاستدعاء التي تعالج النتيجة. يتلقّى ردّ الاتصال هذا مسار الملف الشخصي المحفوظ من خلالgetResultFilePath(). - إضافة عوامل تشغيل: لتسجيل قائمة عوامل التشغيل في
ProfilingManagerباستخدامaddProfilingTriggers. - Fire event: تنشر دالة استدعاء
ChoreographerتستدعيreportFullyDrawn()بعد رسم الإطار التالي، ما يؤدي إلى إرسال الحدثTRIGGER_TYPE_APP_FULLY_DRAWNإلى النظام، وبالتالي تفعيل عملية جمع الملفات الشخصية بافتراض أنّ عملية تتبُّع النظام في الخلفية كانت قيد التشغيل وأنّ حصة محدِّد المعدّل متاحة. لحدوث هذا المشغّل، تأكَّد من أنّ تطبيقك يستدعيreportFullyDrawn().
مراحل نشاط المشغّلات
تظلّ عوامل التفعيل المسجَّلة محفوظة حتى بعد إعادة تشغيل التطبيق والنظام. لا حاجة إلى إعادة تسجيل عوامل التفعيل في كل مرة يتم فيها تشغيل تطبيقك أو بعد إعادة تشغيل النظام، فبعد تسجيل عوامل التفعيل باستخدام addProfilingTriggers، يحتفظ النظام بها تلقائيًا لتطبيقك إلى أن تتم إزالتها أو إلغاء تثبيت التطبيق.
حالات إلغاء تسجيل عوامل التشغيل
بما أنّ عوامل التفعيل المسجَّلة تظل محفوظة عند إعادة تشغيل التطبيق والنظام،
فإنّ تخطّي addProfilingTriggers في عمليات التشغيل اللاحقة لا يؤدي إلى إيقاف عوامل التفعيل
المسجَّلة في جلسة سابقة. لإيقاف تسجيل الملفات الشخصية لأحداث معيّنة أو لجميع الأحداث، يمكنك استدعاء removeProfilingTriggersByType أو clearProfilingTriggers بشكل صريح.
يجب إلغاء تسجيل عوامل التشغيل في الحالات التالية:
- استهداف المجموعات النموذجية أو التراجع عن علامات الإعداد عن بُعد: يمكنك تقسيم الملفات الشخصية على مستوى المجموعات النموذجية باستخدام علامات الإعداد عن بُعد أو اختبارات A/B. عندما يغادر جهاز المجموعة النموذجية أو يتم إيقاف علامة، يجب إلغاء تسجيل المشغّلات.
- إنهاء حملة تصحيح الأخطاء: بعد جمع ما يكفي من الملفات الشخصية لتشخيص مشكلة أو إصلاحها، يمكنك إزالة المشغّل. يؤدي إلغاء تسجيل المشغّلات غير الضرورية إلى الحفاظ على مساحة التخزين على الجهاز وحصة محدّد معدّل الطلبات في تطبيقك لطلبات جمع البيانات الأخرى.
مراحل نشاط معاودة الاتصال
على عكس طلبات إنشاء الملفات الشخصية المباشرة، لا تقدّم الملفات الشخصية المستندة إلى المشغّلات النتائج إلا إلى
مستمع عام مسجَّل في registerForAllProfilingResults. في دالة الاستدعاء، يمكنك استدعاء ProfilingResult.getTriggerType لتحديد المشغّل الذي بدأ عملية الالتقاط، واستدعاء ProfilingResult.getResultFilePath لتحديد موقع ملف الملف الشخصي المحفوظ. لمزيد من التفاصيل حول أسماء ملفات الملفات الشخصية التي يتم تفعيلها، وسحب الملفات باستخدام adb، وتحميل النتائج في الخلفية، يُرجى الاطّلاع على استرداد الملفات الشخصية وتحميلها.
على الرغم من أنّ المشغّلات تستمر في العمل بعد إعادة تشغيل التطبيق والنظام، لا تستمر عمليات استدعاء النتائج. سجِّل دالة الاستدعاء في Executor في الخلفية بعد اكتمال بدء تشغيل التطبيق (حتى لا تبطئ عملية التشغيل على البارد) لتلقّي الملفات الشخصية في كلا السيناريوهَين التاليَين:
- أثناء تشغيل تطبيقك: بالنسبة إلى العوامل التي لا تؤدي إلى إيقاف تطبيقك أو تعطّله، يستدعي النظام دالة الاستدعاء في
Executorالمقدَّم عند حدوث العامل وحفظ الملف الشخصي. بعد إنهاء التطبيق: بالنسبة إلى العوامل التي غالبًا ما تتضمّن إنهاء التطبيق أو تسبقه (مثل
TRIGGER_TYPE_ANRأوTRIGGER_TYPE_OOMأوTRIGGER_TYPE_KILL_RECENTS)، أو إذا توقّف تطبيقك قبل انتهاء عملية التسجيل، يحفظ النظام الملف الشخصي في الخلفية ويضع النتيجة في قائمة الانتظار على مستوى عمليات إعادة تشغيل التطبيق والنظام. يحتفظ النظام بالنتائج التي لم يتم تسليمها في قائمة الانتظار لمدة تصل إلى 7 أيام، ثم يسلّمها في المرة التالية التي يتم فيها تشغيل تطبيقك واستدعاءregisterForAllProfilingResults.
آلية عمل ميزة "التتبُّع في الخلفية"
لتحقيق التوازن بين عبء جمع بيانات الملفات الشخصية والتقاط العناصر المفيدة، لا يشغّل النظام عمليات تتبُّع في الخلفية بشكل مستمر. بدلاً من ذلك، يتم أخذ عيّنات بشكل دوري من خلال بدء عمليات تتبُّع في الخلفية على فترات عشوائية.
تستخدم عمليات التتبُّع في الخلفية التي يشغّلها النظام مخزنًا مؤقتًا حلقيًا بحجم أقصى يحدّده النظام. عند امتلاء المخزن المؤقت، تستبدل بيانات التتبُّع الجديدة البيانات الأقدم. As shown in Figure 1, when a registered trigger fires while a background trace is active and rate-limiter quota is available, the system saves the ring buffer snapshot containing the most recent activity leading up to the trigger.
ضبط فترة تهدئة خاصة بمشغّل معيّن
يمكن أن تستهلك عوامل التفعيل العالية التردد بسرعة الحصة المحدّدة لمعدّل نقل البيانات في تطبيقك.
لمنع نوع واحد من المشغّلات من استنفاد حصتك، استخدِم
setRateLimitingPeriodHours لإضافة حدّ أدنى لفترة تعافي لكل مشغّل
بالإضافة إلى محدّد معدّل النظام.
تصحيح أخطاء المشغّلات محليًا
بما أنّ عمليات تتبُّع الأداء في الخلفية يتم تشغيلها على فترات عشوائية في مرحلة الإنتاج، يتطلّب اختبار المشغّلات محليًا فرض عملية تتبُّع مستمرة في الخلفية وتجاوز محدّد معدّل البيانات على مستوى النظام لحزمتك (لا يزال أي وقت تهدئة لكل مشغّل يتم ضبطه باستخدام setRateLimitingPeriodHours ساريًا، ولا ينطبق rate_limiter.disabled إلا على طلبات requestProfiling المستندة إلى التطبيق).
للاطّلاع على أوامر adb لفرض عمليات التتبُّع في الخلفية ومحاكاة المشغّلات من سطر الأوامر وفحص حالة الخدمة، يُرجى مراجعة فرض تفعيل عمليات التتبُّع في الخلفية لاختبار المشغّلات في أوامر تصحيح الأخطاء لإنشاء الملفات الشخصية المحلية.