Profilleri alma ve yükleme

Uygulama tabanlı profil veya tetikleyici tabanlı profil yakaladığınızda ProfilingManager, tamamlanan dosyayı cihaza kaydeder ve kayıtlı geri çağırma işlevinize bir ProfilingResult gönderir. Kayıtlı profilin yolunu almak için ProfilingResult.getResultFilePath işlevini çağırın:

Cihazdan profilleri alma

Bu bölümde, ProfilingManager uygulamasının profilleri cihazda nerede depoladığı, otomatik dosya temizleme işleminin nasıl çalıştığı ve adb kullanarak dosyaların yerel olarak nasıl alınacağı açıklanmaktadır.

Dosya konumları ve adlandırma biçimleri

ProfilingManager, düzenlenmiş profilleri /data/user/0/<app>/files/profiling/ konumundaki uygulamaya özel depolama dizininize kaydeder. Dosya adı biçimi, profilin nasıl yakalandığına bağlıdır:

  • Uygulama tabanlı profiller:

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

    Profil istenirken etiket sağlanmadıysa <tag>_ atlanır: profile_<datetime>_uid-<uid>.<profile-type-ext>.

  • Tetikleyici tabanlı profiller:

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

Nerede:

  • <app>, uygulamanızın paket adıdır.
  • <tag>, setTag ile yapılandırılan veya requestProfiling öğesine iletilen, arayan tarafından sağlanan etiketin ilk 20 alfanümerik karakterini (ve tireleri) içerir. a-z, 0-9 ve - dışındaki tüm karakterler kaldırılır ve küçük harfe dönüştürülür.
  • <trigger_type>, ProfilingTrigger adresindeki tetikleyici için tam sayı sabit kodudur. Dosya adını ayrıştırmak yerine kodda her zaman ProfilingResult.getTriggerType yöntemini çağırın.
  • <datetime>, profilin kaydedildiği tarih ve saattir (yyyy-MM-dd-HH-mm-ss-SSS).
  • <uid>, uygulamanızın Linux kullanıcı kimliğidir (son Profiling modül sürümlerine dahildir).
  • <profile-type-ext>, yakalanan profil türünün dosya uzantısıdır:
    • Sistem izleri için .perfetto-trace
    • Java yığın dökümleri için .perfetto-java-heap-dump
    • Öbek profilleri için .perfetto-heap-profile
    • Yığın örnekleme profilleri için .perfetto-stack-sample

Cihazdaki depolama alanı ve temizleme

Cihaz depolama alanında hemen yer açmak için başarılı bir yükleme işleminden hemen sonra yükleme çalışanınızdaki her profil dosyasını silin (Otomatik temizleme yalnızca ProfilingManager, uygulamanıza sonuçları ilettiğinde çalışır. Aksi takdirde, uygulamanız bir kampanyayı sonlandırdıktan sonra geri çağırmaları kaydetmeyi durdurursa yüklenmeyen dosyalar diskte kalabilir). Son Profiling modül sürümlerinde yedek olarak ProfilingManager, yeni sonuçlar yayınlandığında uygulamaya özel depolama dizininizdeki 5 günden eski yayınlanmış dosyaları da otomatik olarak siler.

WorkManager ile üretimdeki profilleri yükleme

Profil dosyalarının boyutu birkaç megabayt olabileceğinden, canlı sürüm yüklemelerini cihazın sınırsız bir ağda (kablosuz), şarjda ve boştayken arka planda gerçekleşecek şekilde planlayın.

Yüklemeden önce profil dosyasını sıkıştırın (ör. GZIPOutputStream veya ZipOutputStream kullanarak). Perfetto protobuf profilleri ve Java yığın dökümleri önemli ölçüde sıkıştırılarak ağ bant genişliği ve arka uç depolama maliyetleri azaltılır.

WorkManager bağımlılıklarını ekleme

ProfilingManager, bulut platformundan bağımsızdır. Bu sayede, WorkManager kullanarak profillerin herhangi bir arka uca yüklenmesini planlayabilirsiniz. WorkManager kitaplığını build.gradle.kts dosyanıza ekleyin:

Kotlin

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

Modern

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

Yükleme işi planlama

Uygulamanız ProfilingResult aldığında yükleme işini planlayın. Aşağıdaki örnekte ilk profil oluşturma isteği atlanmıştır. Tam bir istek örneği için Sistem izi kaydetme bölümüne bakın.

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());
}

Kodun adım adım açıklaması

Yukarıdaki örnekte aşağıdaki adımlar uygulanır:

  • Çalışanı tanımlayın: Worker sınıfını genişleten bir TraceUploadWorker sınıfı oluşturun. Profil dosyasının hâlâ mevcut olduğunu doğrulamak için doWork uygulayın, arka uç SDK'nızı veya HTTP istemcinizi kullanarak dosyayı sıkıştırıp yükleyin ve yükleme başarılı olduktan sonra yerel dosyayı silin.
  • Çalışmayı planlayın:
    • Çalışanınız için bir OneTimeWorkRequest oluşturun.
    • Kısıtlamalar ayarlayın: Yüklemenin yalnızca cihaz kablosuz ağa bağlıyken, şarj olurken ve boştayken çalışması için setRequiredNetworkType(NetworkType.UNMETERED), setRequiresDeviceIdle(true) ve setRequiresCharging(true) öğelerini kullanın.
    • Veri aktarma: Profil yolunu getResultFilePath üzerinden çalışan düğüme aktarmak için setInputData kullanın.
    • Sıraya ekleme: WorkManager.enqueue yöntemini çağırarak isteği WorkManager hizmetine gönderin.

Sonraki adımlar

Profilleri aldıktan veya yükledikten sonra Perfetto kullanıcı arayüzünde görselleştirebilir, PerfettoSQL ile profilleri tek tek sorgulayabilir, izleri toplu olarak analiz edebilir veya profilleri yapay zeka ile analiz edebilirsiniz. Ölçeklenebilir bir sunucu tarafı analiz ardışık düzeni oluşturma konusunda rehberlik için Bigtrace'i Kubernetes'te dağıtma başlıklı makaleyi inceleyin.