Seja para capturar um perfil orientado por app ou um perfil baseado em acionador,
o ProfilingManager salva o arquivo concluído no dispositivo e envia um
ProfilingResult para o callback registrado. Chame
ProfilingResult.getResultFilePath para receber o caminho do perfil salvo:
- Durante o teste local: extraia o arquivo para o computador usando
adb. - Em produção: transmita o caminho para um job
WorkManagerque compacta e faz upload do perfil para o servidor.
Recuperar perfis de um dispositivo
Nesta seção, descrevemos onde o ProfilingManager armazena perfis no dispositivo, como funciona a limpeza automática de arquivos e como extrair arquivos localmente usando o adb.
Locais de arquivos e formatos de nomenclatura
O ProfilingManager salva perfis editados no diretório de armazenamento específico do app em /data/user/0/<app>/files/profiling/. O formato do nome do arquivo
depende de como o perfil foi capturado:
Perfis orientados por apps:
profile_<tag>_<datetime>_uid-<uid>.<profile-type-ext>Se nenhuma tag tiver sido fornecida ao solicitar o perfil,
<tag>_será omitido:profile_<datetime>_uid-<uid>.<profile-type-ext>.Perfis baseados em gatilhos:
profile_trigger-type-<trigger_type>_<datetime>_uid-<uid>.<profile-type-ext>
Em que:
<app>é o nome do pacote do seu app.<tag>é composto pelos primeiros 20 caracteres alfanuméricos (e hifens) da tag fornecida pelo autor da chamada configurada comsetTagou transmitida pararequestProfiling, convertida em minúsculas com todos os caracteres fora dea-z,0-9e-removidos.<trigger_type>é o código de constante de número inteiro para o acionador deProfilingTrigger. Sempre chameProfilingResult.getTriggerTypeno código em vez de analisar o nome do arquivo.<datetime>é a data e a hora em que o perfil foi registrado (yyyy-MM-dd-HH-mm-ss-SSS).<uid>é o ID do usuário do Linux do seu app (incluído nas versões recentes do móduloProfiling).<profile-type-ext>é a extensão de arquivo do tipo de perfil capturado:.perfetto-tracepara rastreamentos do sistema.perfetto-java-heap-dumppara heap dumps do Java.perfetto-heap-profilepara perfis de alocação heap.perfetto-stack-samplepara perfis de amostragem de pilha
Armazenamento e limpeza no dispositivo
Para liberar o armazenamento do dispositivo imediatamente, exclua cada arquivo de perfil no worker de upload
logo após um upload bem-sucedido. Como a limpeza automática só
é executada quando o ProfilingManager envia resultados ao app, os arquivos não enviados podem
permanecer no disco se o app parar de registrar callbacks após o término de uma
campanha. Como alternativa nas versões recentes do módulo Profiling,
o ProfilingManager também exclui automaticamente os arquivos entregues no diretório de armazenamento
específico do app que têm mais de cinco dias quando novos resultados são
entregues.
Fazer upload de perfis na produção com o WorkManager
Como os arquivos de perfil podem ter vários megabytes, programe uploads de produção em segundo plano quando o dispositivo estiver em uma rede ilimitada (Wi-Fi), carregando e ocioso.
Antes de fazer o upload, compacte o arquivo de perfil (por exemplo, usando
GZIPOutputStream ou ZipOutputStream). Os perfis de protobuf do Perfetto e os heap dumps
do Java são compactados significativamente, reduzindo a largura de banda da rede e os custos de armazenamento
de back-end.
Adicionar dependências do WorkManager
O ProfilingManager é independente de nuvem, então é possível programar o upload de perfis
para qualquer back-end usando WorkManager. Adicione a biblioteca WorkManager ao arquivo
build.gradle.kts:
Kotlin
dependencies { implementation("androidx.work:work-runtime:2.12.0") }
Groovy
dependencies { implementation 'androidx.work:work-runtime:2.12.0' }
Programar um job de upload
Quando o app receber um ProfilingResult, programe o job de upload. O
exemplo a seguir omite a solicitação de criação de perfil inicial. Para ver um exemplo de solicitação
completo, consulte Gravar um rastreamento do sistema.
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()); }
Tutorial do código
O exemplo anterior executa as seguintes etapas:
- Defina o worker: crie uma classe
TraceUploadWorkerque estendaWorker. ImplementedoWorkpara verificar se o arquivo de perfil ainda existe, compacte e faça upload dele usando o SDK de back-end ou o cliente HTTP e exclua o arquivo local após o upload. - Programar o trabalho:
- Crie um
OneTimeWorkRequestpara o worker. - Definir restrições: use
setRequiredNetworkType(NetworkType.UNMETERED),setRequiresDeviceIdle(true)esetRequiresCharging(true)para que o upload seja executado apenas quando o dispositivo estiver conectado ao Wi-Fi, carregando e ocioso. - Transmitir dados: use
setInputDatapara transmitir o caminho do perfil degetResultFilePathpara o worker. - Enqueue: envie a solicitação para
WorkManagerchamandoWorkManager.enqueue.
- Crie um
Próximas etapas
Depois de recuperar ou fazer upload de perfis, visualize-os na interface do Perfetto, consulte perfis individuais com o PerfettoSQL, analise traces em massa ou analise perfis com IA. Para orientações sobre como configurar um pipeline de análise escalonável do lado do servidor, consulte Como implantar o Bigtrace no Kubernetes.