تتيح ProfilingManager تسجيل الملفات الشخصية استنادًا إلى مشغّلات النظام. يدير النظام عملية التسجيل ويوفّر الملف الناتج لتطبيقك.
تكون المشغّلات مرتبطة بالأحداث المهمة للأداء. تقدّم الملفات الشخصية المسجّلة من النظام معلومات مفصّلة لتصحيح الأخطاء في تجارب المستخدمين المهمة (CUJ) المرتبطة بهذه المشغّلات.
تسجيل البيانات السابقة
تتطلّب العديد من المشغّلات تحليل البيانات السابقة التي أدّت إلى الحدث. وغالبًا ما يكون المشغّل نتيجة لمشكلة وليس السبب الرئيسي. إذا بدأت تسجيل الملف الشخصي بعد حدوث المشكلة، قد لا تتمكّن من تحديد السبب الجذري.
على سبيل المثال، تتسبّب عملية طويلة الأمد في سلسلة تعليمات واجهة المستخدم في حدوث خطأ التطبيق لا يستجيب (ANR). وبحلول الوقت الذي يرصد فيه النظام خطأ ANR ويُرسل إشارة إلى التطبيق، قد تكون العملية قد انتهت. وبالتالي، لن يتم تسجيل أي بيانات حظر في الملف الشخصي الذي تم إنشاؤه في تلك اللحظة.
لا يمكن التنبؤ بدقة بموعد حدوث بعض المشغّلات، ما يجعل من المستحيل بدء ملف شخصي يدويًا مسبقًا.
لماذا يُنصح باستخدام ميزة "التسجيل المستند إلى المشغِّل"؟
السبب الرئيسي لاستخدام مشغّلات إنشاء الملفات الشخصية هو تسجيل البيانات الخاصة بالأحداث غير المتوقّعة التي يستحيل على التطبيق بدء تسجيلها يدويًا قبل وقوعها. يمكن استخدام مشغّلات إنشاء الملفات الشخصية لإجراء ما يلي:
- تصحيح أخطاء الأداء: يمكنك تشخيص أخطاء ANR وتسريب الذاكرة ومشاكل الثبات الأخرى.
- تحسين رحلات المستخدمين الرئيسية: يمكنك تحليل المسارات وتحسينها، مثل بدء تشغيل التطبيق.
- فهم سلوك المستخدم: يمكنك الحصول على إحصاءات عن الأحداث، مثل عمليات الخروج من التطبيق التي يبدأها المستخدم.
إعداد مشغّل
يوضّح الرمز التالي كيفية التسجيل في مشغّل TRIGGER_TYPE_APP_FULLY_DRAWN وتطبيق الحدّ الأقصى لعدد المرات التي يمكن تشغيله فيها.
Kotlin
fun recordWithTrigger() { val profilingManager = applicationContext.getSystemService(ProfilingManager::class.java) val triggers = ArrayList<ProfilingTrigger>() val triggerBuilder = ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN) .setRateLimitingPeriodHours(1) triggers.add(triggerBuilder.build()) val mainExecutor: 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(mainExecutor, resultCallback) profilingManager.addProfilingTriggers(triggers)
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 mainExecutor = 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(mainExecutor, resultCallback); profilingManager.addProfilingTriggers(triggers);
ينفّذ الرمز الخطوات التالية:
- Get the manager: يسترد خدمة
ProfilingManager. - تحديد عبارة تشغيل: ينشئ
ProfilingTriggerلـTRIGGER_TYPE_APP_FULLY_DRAWN. يحدث هذا الحدث عندما يبلّغ التطبيق بأنّه انتهى من بدء التشغيل وأصبح تفاعليًا. - ضبط حدود المعدّل: يفرض هذا الإجراء حدًا للمعدّل يبلغ ساعة واحدة على هذا المشغّل المحدّد (
setRateLimitingPeriodHours(1))، ما يمنع التطبيق من تسجيل أكثر من ملف شخصي واحد لبدء التشغيل في الساعة. - تسجيل أداة معالجة: يتم استدعاء
registerForAllProfilingResultsلتحديد دالة الرجوع التي تعالج النتيجة. يتلقّى هذا الإجراء مسار الملف الشخصي المحفوظ من خلالgetResultFilePath(). - إضافة عوامل مشغّلة: تسجّل هذه السمة قائمة العوامل المشغّلة في
ProfilingManagerباستخدامaddProfilingTriggers. - حدث التشغيل: يستدعي
reportFullyDrawn()، ما يؤدي إلى إرسال الحدثTRIGGER_TYPE_APP_FULLY_DRAWNإلى النظام لتشغيل عملية جمع الملفات الشخصية، وذلك بافتراض أنّ عملية تتبُّع خلفية للنظام كانت قيد التشغيل وأنّ هناك حصة متاحة من أداة تحديد المعدّل. توضّح هذه الخطوة الاختيارية مسارًا كاملاً، لأنّ تطبيقك يجب أن يستدعيreportFullyDrawn()لتنفيذ هذا المشغّل.
استرداد عملية التتبُّع
يحفظ النظام الملفات الشخصية المستندة إلى المشغّلات في الدليل نفسه الذي يتم فيه حفظ الملفات الشخصية الأخرى. يتّبع اسم ملف عمليات التتبُّع التي يتم تشغيلها التنسيق التالي:
profile_trigger_<profile_type_code>_<datetime>.<profile-type-name>
يمكنك سحب الملف باستخدام "أداة تصحيح أخطاء Android" (ADB). على سبيل المثال، لاسترداد تتبُّع النظام الذي تم تسجيله باستخدام الرمز النموذجي باستخدام ADB، قد يبدو على النحو التالي:
adb pull /data/user/0/com.example.sampleapp/files/profiling/profile_trigger_1_2025-05-06-14-12-40.perfetto-trace
لمعرفة تفاصيل حول عرض هذه عمليات التتبُّع بشكل مرئي، يُرجى الاطّلاع على استرداد بيانات إنشاء الملفات الشخصية وتحليلها.
طريقة عمل ميزة "تتبُّع الخلفية"
لالتقاط البيانات من قبل بدء عملية التشغيل، يبدأ نظام التشغيل بشكل دوري عملية تتبُّع في الخلفية. إذا تم تشغيل عملية تتبُّع في الخلفية أثناء تفعيل هذا المشغّل وكان تطبيقك مسجّلاً لتلقّي إشعارات بشأن هذا المشغّل، سيحفظ النظام ملف التتبُّع في دليل تطبيقك. سيتضمّن الملف الشخصي بعد ذلك معلومات أدّت إلى تشغيل الإجراء.
بعد حفظ الملف الشخصي، يُرسل النظام إشعارًا إلى تطبيقك باستخدام دالة الرجوع
المقدَّمة إلى registerForAllProfilingResults. يوفر رد الاتصال هذا المسار إلى الملف الشخصي الذي تم التقاطه، ويمكن الوصول إليه من خلال استدعاء ProfilingResult#getResultFilePath().
ولتقليل التأثير على أداء الجهاز وعمر البطارية، لا يشغّل النظام عمليات التتبُّع في الخلفية بشكل مستمر. بدلاً من ذلك، تستخدم طريقة أخذ العيّنات. يبدأ النظام بشكل عشوائي عملية تتبُّع في الخلفية خلال إطار زمني محدّد (مع مدة دنيا وقصوى). يؤدي توزيع عمليات التتبُّع هذه بشكل عشوائي إلى تحسين تغطية المشغّلات.
تتضمّن الملفات الشخصية التي يتم تشغيلها بواسطة النظام حدًا أقصى يحدّده النظام، لذا تستخدم مخزنًا مؤقتًا حلقيًا. بعد امتلاء المخزن المؤقت، تحلّ بيانات التتبُّع الجديدة محلّ البيانات الأقدم. كما هو موضّح في الشكل 1، قد لا يغطّي التتبُّع الذي تم تسجيله المدة الكاملة للتسجيل في الخلفية إذا تم ملء المخزن المؤقت، بل يمثّل النشاط الأخير الذي أدّى إلى بدء التسجيل.
تنفيذ الحدّ الأقصى لمعدّل الزحف الخاص بالمشغّلات
يمكن أن تؤدي المشغّلات العالية التكرار إلى استهلاك حصة الحدّ الأقصى المسموح به في تطبيقك بسرعة. لفهم أداة تحديد المعدّل بشكل أفضل، ننصحك بالاطّلاع على طريقة عمل أداة تحديد المعدّل. لمنع نوع واحد من المشغّلات من استنفاد حصتك، يمكنك تنفيذ تحديد المعدّل الخاص بالمشغّل.
تتيح السمة ProfilingManager الحدّ من المعدّل الخاص بمشغّل محدّد يحدّده التطبيق. يتيح لك ذلك إضافة طبقة أخرى من التقييد المستند إلى الوقت بالإضافة إلى أداة تحديد المعدّل الحالية. استخدِم واجهة برمجة التطبيقات setRateLimitingPeriodHours لضبط وقت
استراحة محدّد لمشغّل. بعد انتهاء فترة الانتظار، يمكنك تفعيلها مرة أخرى.
تصحيح أخطاء المشغّلات محليًا
بما أنّ عمليات التتبُّع في الخلفية يتم تنفيذها في أوقات عشوائية، يصعب تصحيح أخطاء المشغّلات على الجهاز. لفرض تتبُّع في الخلفية بغرض الاختبار، استخدِم أمر ADB التالي:
adb shell device_config put profiling_testing system_triggered_profiling.testing_package_name <com.example.myapp>
يفرض هذا الأمر على النظام بدء تتبُّع مستمر في الخلفية للحزمة المحدّدة، ما يتيح لكل مشغّل إمكانية جمع ملف تعريف إذا سمح بذلك أداة تحديد المعدّل.
يمكنك أيضًا تفعيل خيارات تصحيح الأخطاء الأخرى، مثل إيقاف أداة تحديد عدد مرات الاستخدام عند تصحيح الأخطاء محليًا. لمزيد من المعلومات، يُرجى الاطّلاع على أوامر تصحيح الأخطاء الخاصة بإنشاء الملفات الشخصية المحلية.