Niezależnie od tego, czy przechwycisz profil oparty na aplikacji czy profil oparty na aktywatorze, ProfilingManager zapisze gotowy plik na urządzeniu i wyśle ProfilingResult do zarejestrowanego wywołania zwrotnego. Wywołaj ProfilingResult.getResultFilePath, aby uzyskać ścieżkę zapisanego profilu:
- Podczas testowania lokalnego: pobierz plik na komputer za pomocą polecenia
adb. - W środowisku produkcyjnym: podaj ścieżkę do zadania
WorkManager, które kompresuje i przesyła profil na serwer.
Pobieranie profili z urządzenia
W tej sekcji opisano, gdzie ProfilingManager przechowuje profile na urządzeniu, jak działa automatyczne czyszczenie plików i jak pobierać pliki lokalnie za pomocą adb.
Lokalizacje plików i formaty nazw
ProfilingManager zapisuje profile z usuniętymi danymi w katalogu pamięci aplikacji w /data/user/0/<app>/files/profiling/. Format nazwy pliku zależy od sposobu przechwycenia profilu:
Profile oparte na aplikacjach:
profile_<tag>_<datetime>_uid-<uid>.<profile-type-ext>Jeśli podczas wysyłania żądania profilu nie podano tagu, parametr
<tag>_jest pomijany:profile_<datetime>_uid-<uid>.<profile-type-ext>.Profile oparte na aktywatorach:
profile_trigger-type-<trigger_type>_<datetime>_uid-<uid>.<profile-type-ext>
Gdzie:
<app>to nazwa pakietu aplikacji.<tag>to pierwsze 20 znaków alfanumerycznych (i łączników) tagu podanego przez element wywołujący, który został skonfigurowany za pomocąsetTaglub przekazany dorequestProfiling, przekonwertowany na małe litery i pozbawiony znaków spoza zakresua-z,0-9i-.<trigger_type>to kod stałej liczby całkowitej dla aktywatora zProfilingTrigger. Zawsze wywołuj w kodzieProfilingResult.getTriggerType, zamiast analizować nazwę pliku.<datetime>to data i godzina zarejestrowania profilu (yyyy-MM-dd-HH-mm-ss-SSS).<uid>to identyfikator użytkownika Linuksa Twojej aplikacji (zawarty w najnowszych wersjach modułuProfiling).<profile-type-ext>to rozszerzenie pliku dla przechwyconego typu profilu:.perfetto-tracedla śledzenia systemu.perfetto-java-heap-dumpw przypadku zrzutów sterty Java.perfetto-heap-profiledla profili sterty.perfetto-stack-samplew przypadku profili próbkowania stosu
Pamięć na urządzeniu i czyszczenie
Aby szybko zwolnić pamięć urządzenia, usuń każdy plik profilu z procesu roboczego przesyłania natychmiast po udanym przesłaniu (ponieważ automatyczne czyszczenie jest uruchamiane tylko wtedy, gdy ProfilingManager dostarcza wyniki do aplikacji, nieprzesłane pliki mogą pozostać na dysku, jeśli aplikacja przestanie rejestrować wywołania zwrotne po zakończeniu kampanii). W przypadku ostatnich wersji modułu Profiling ProfilingManager automatycznie usuwa też dostarczone pliki w katalogu pamięci aplikacji, które są starsze niż 5 dni, gdy dostarczane są nowe wyniki.
Przesyłanie profili w środowisku produkcyjnym za pomocą WorkManagera
Pliki profilu mogą mieć rozmiar kilku megabajtów, dlatego zaplanuj przesyłanie plików produkcyjnych w tle, gdy urządzenie jest połączone z siecią bez taryfowego rozliczania danych (Wi-Fi), ładuje się i jest bezczynne.
Przed przesłaniem skompresuj plik profilu (np. za pomocą GZIPOutputStream lub ZipOutputStream). Profile protobuf Perfetto i zrzuty sterty Javy znacznie się kompresują, co zmniejsza przepustowość sieci i koszty pamięci masowej backendu.
Dodawanie zależności biblioteki WorkManager
ProfilingManager nie jest powiązany z żadną chmurą, więc możesz zaplanować przesyłanie profili do dowolnego backendu za pomocą WorkManager. Dodaj bibliotekę WorkManager do pliku build.gradle.kts:
Kotlin
dependencies { implementation("androidx.work:work-runtime:2.12.0") }
Dynamiczny
dependencies { implementation 'androidx.work:work-runtime:2.12.0' }
Planowanie zadania przesyłania
Gdy aplikacja otrzyma ProfilingResult, zaplanuj zadanie przesyłania. W poniższym przykładzie pominięto początkowe żądanie profilowania. Pełny przykład żądania znajdziesz w artykule Rejestrowanie śledzenia systemu.
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()); }
Przewodnik po kodzie
W powyższym przykładzie wykonywane są te czynności:
- Zdefiniuj instancję roboczą: utwórz klasę
TraceUploadWorkerrozszerzającą klasęWorker. ZaimplementujdoWork, aby sprawdzić, czy plik profilu nadal istnieje, skompresuj go i prześlij za pomocą pakietu SDK backendu lub klienta HTTP, a po zakończeniu przesyłania usuń plik lokalny. - Zaplanuj pracę:
- Utwórz
OneTimeWorkRequestdla instancji roboczej. - Ustaw ograniczenia: użyj
setRequiredNetworkType(NetworkType.UNMETERED),setRequiresDeviceIdle(true)isetRequiresCharging(true), aby przesyłanie odbywało się tylko wtedy, gdy urządzenie jest połączone z Wi-Fi, ładuje się i jest bezczynne. - Przekazywanie danych: użyj
setInputData, aby przekazać ścieżkę profilu zgetResultFilePathdo instancji roboczej. - Enqueue: przesyła żądanie do
WorkManager, wywołującWorkManager.enqueue.
- Utwórz
Dalsze kroki
Po pobraniu lub przesłaniu profili możesz wyświetlić je w interfejsie Perfetto, wykonać zapytania dotyczące poszczególnych profili za pomocą PerfettoSQL, przeanalizować ślady zbiorczo lub przeanalizować profile za pomocą AI. Wskazówki dotyczące konfigurowania skalowalnego potoku analizy po stronie serwera znajdziesz w artykule Wdrażanie Bigtrace w Kubernetes.