Mengambil dan mengupload profil

Baik Anda mengambil profil berbasis aplikasi atau profil berbasis pemicu, ProfilingManager akan menyimpan file yang telah selesai di perangkat dan mengirimkan ProfilingResult ke callback terdaftar Anda. Panggil ProfilingResult.getResultFilePath untuk mendapatkan jalur profil yang disimpan:

Mengambil profil dari perangkat

Bagian ini menjelaskan tempat ProfilingManager menyimpan profil di perangkat, cara kerja pembersihan file otomatis, dan cara mengambil file secara lokal menggunakan adb.

Lokasi file dan format penamaan

ProfilingManager menyimpan profil yang disamarkan di direktori penyimpanan khusus aplikasi Anda di /data/user/0/<app>/files/profiling/. Format nama file bergantung pada cara profil diambil:

  • Profil berbasis aplikasi:

    profile_<tag>_<datetime>_uid-<uid>.<profile-type-ext>
    

    Jika tidak ada tag yang diberikan saat meminta profil, <tag>_ akan dihilangkan: profile_<datetime>_uid-<uid>.<profile-type-ext>.

  • Profil berbasis pemicu:

    profile_trigger-type-<trigger_type>_<datetime>_uid-<uid>.<profile-type-ext>
    

Dengan:

  • <app> adalah nama paket aplikasi Anda.
  • <tag> adalah hingga 20 karakter alfanumerik pertama (dan tanda hubung) dari tag yang disediakan pemanggil yang dikonfigurasi dengan setTag atau diteruskan ke requestProfiling, dikonversi menjadi huruf kecil dengan karakter apa pun di luar a-z, 0-9, dan - dihapus.
  • <trigger_type> adalah kode konstanta bilangan bulat untuk pemicu dari ProfilingTrigger. Selalu panggil ProfilingResult.getTriggerType dalam kode, bukan mengurai nama file.
  • <datetime> adalah tanggal dan waktu profil dicatat (yyyy-MM-dd-HH-mm-ss-SSS).
  • <uid> adalah ID pengguna Linux aplikasi Anda (disertakan pada versi modul Profiling terbaru).
  • <profile-type-ext> adalah ekstensi file untuk jenis profil yang diambil:
    • .perfetto-trace untuk pelacakan sistem
    • .perfetto-java-heap-dump untuk heap dump Java
    • .perfetto-heap-profile untuk profil heap
    • .perfetto-stack-sample untuk profil pengambilan sampel stack

Penyimpanan dan pembersihan di perangkat

Untuk segera mengosongkan penyimpanan perangkat, hapus setiap file profil di worker upload segera setelah upload berhasil (karena pembersihan otomatis hanya berjalan saat ProfilingManager mengirimkan hasil ke aplikasi Anda, file yang tidak diupload dapat tetap berada di disk jika aplikasi Anda berhenti mendaftarkan callback setelah mengakhiri kampanye). Sebagai penggantian pada versi modul Profiling terbaru, ProfilingManager juga otomatis menghapus file yang dikirim di direktori penyimpanan khusus aplikasi Anda yang berusia lebih dari 5 hari saat hasil baru dikirim.

Mengupload profil dalam produksi dengan WorkManager

Karena file profil dapat berukuran beberapa megabyte, jadwalkan upload produksi di latar belakang saat perangkat berada di jaringan tidak berbayar (Wi-Fi), sedang mengisi daya, dan tidak ada aktivitas.

Sebelum mengupload, kompresi file profil (misalnya, menggunakan GZIPOutputStream atau ZipOutputStream). Profil protobuf Perfetto dan heap dump Java dikompresi secara signifikan, sehingga mengurangi bandwidth jaringan dan biaya penyimpanan backend.

Menambahkan dependensi WorkManager

ProfilingManager bersifat cloud-agnostik, sehingga Anda dapat menjadwalkan upload profil ke backend mana pun menggunakan WorkManager. Tambahkan library WorkManager ke file build.gradle.kts Anda:

Kotlin

   dependencies {
       implementation("androidx.work:work-runtime:2.12.0")
   }
   

Groovy

   dependencies {
       implementation 'androidx.work:work-runtime:2.12.0'
   }
   

Menjadwalkan tugas upload

Saat aplikasi Anda menerima ProfilingResult, jadwalkan tugas upload. Contoh berikut menghilangkan permintaan pembuatan profil awal; untuk contoh permintaan lengkap, lihat Merekam pelacakan sistem.

Kotlin

class TraceUploadWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
    override fun doWork(): Result {
        // Perform your uploading work here
        Log.d("ProfileTest", "Uploading trace: " + inputData.getString("PROFILE_PATH"))

        return Result.success()
    }
}

fun setupProfileUploadWorker(profileFilepath: String?) {
    val workMgr = WorkManager.getInstance(applicationContext)
    val workRequestBuilder = OneTimeWorkRequest.Builder(TraceUploadWorker::class)

    val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.UNMETERED)
        .setRequiresDeviceIdle(true)
        .setRequiresCharging(true)
        .build()
    workRequestBuilder.setConstraints(constraints)

    val inputDataBuilder = Data.Builder()
    inputDataBuilder.putString("PROFILE_PATH", profileFilepath)
    workRequestBuilder.setInputData(inputDataBuilder.build())

    workMgr.enqueue(workRequestBuilder.build())
}

Java

public static class TraceUploadWorker extends Worker {

  public TraceUploadWorker(
      @androidx.annotation.NonNull Context context,
      @androidx.annotation.NonNull WorkerParameters workerParams) {
    super(context, workerParams);
  }

  @androidx.annotation.NonNull
  @Override
  public Result doWork() {
    // Perform your uploading work here
    Log.d("ProfileTest", "Uploading trace: " + getInputData().getString("PROFILE_PATH"));

    return Result.success();
  }
}

public void setupProfileUploadWorker(String profileFilepath) {
  WorkManager workMgr = WorkManager.getInstance(getApplicationContext());
  OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder(
      TraceUploadWorker.class);

  Constraints constraints = new Constraints.Builder()
      .setRequiredNetworkType(NetworkType.UNMETERED)
      .setRequiresDeviceIdle(true)
      .setRequiresCharging(true)
      .build();
  workRequestBuilder.setConstraints(constraints);

  Data.Builder inputDataBuilder = new Data.Builder();
  inputDataBuilder.putString("PROFILE_PATH", profileFilepath);
  workRequestBuilder.setInputData(inputDataBuilder.build());

  workMgr.enqueue(workRequestBuilder.build());
}

Panduan kode

Contoh sebelumnya melakukan langkah-langkah berikut:

  • Tentukan pekerja: Buat class TraceUploadWorker yang memperluas Worker. Terapkan doWork untuk memverifikasi bahwa file profil masih ada, kompresi dan upload file tersebut menggunakan SDK backend atau klien HTTP, lalu hapus file lokal setelah upload berhasil.
  • Jadwalkan pekerjaan:
    • Buat OneTimeWorkRequest untuk worker Anda.
    • Menetapkan batasan: Gunakan setRequiredNetworkType(NetworkType.UNMETERED), setRequiresDeviceIdle(true), dan setRequiresCharging(true) agar upload hanya berjalan saat perangkat menggunakan Wi-Fi, mengisi daya, dan tidak ada aktivitas.
    • Teruskan data: Gunakan setInputData untuk meneruskan jalur profil dari getResultFilePath ke worker.
    • Enqueue: Kirim permintaan ke WorkManager dengan memanggil WorkManager.enqueue.

Langkah berikutnya

Setelah mengambil atau mengupload profil, visualisasikan profil di UI Perfetto, buat kueri profil individual dengan PerfettoSQL, analisis rekaman aktivitas secara massal, atau analisis profil dengan AI. Untuk panduan tentang cara menyiapkan pipeline analisis sisi server yang skalabel, lihat Men-deploy Bigtrace di Kubernetes.