Remote Logging to mechanizm wysyłania logów z urządzenia mobilnego na zdalny serwer w celu scentralizowanej analizy i monitorowania. W przeciwieństwie do lokalnego logowania, które przechowuje dane na urządzeniu, zdalne zbieranie pozwala widzieć błędy i anomalie ze wszystkich urządzeń użytkowników w czasie rzeczywistym. Według danych z Sentry Resource Library, aplikacje z remote logging znajdują 92% błędów produkcyjnych w pierwszej godzinie po wydaniu, w porównaniu do 15% przy użyciu tylko raportów awarii. To obowiązkowe narzędzie dla każdego zespołu programistów mobilnych: Firebase Crashlytics, Sentry i Datadog udostępniają gotowe SDK dla iOS i Android.
Najważniejsze
Remote Logging to proces zbierania logów ze zdalnych urządzeń i przesyłania ich na centralny serwer w celu analizy. W kontekście programowania mobilnego remote logging obejmuje nie tylko raporty awarii (crash reporting), ale także niestandardowe zdarzenia, breadcrumbs, metryki wydajności i scenariusze użytkownika.
Główna różnica między remote logging a crash reporting to proaktywność. Crash reporting zbiera tylko dane o awariach aplikacji, które już wystąpiły. Remote logging zbiera sekwencję zdarzeń przed awarią: jakie ekrany otwierał użytkownik, jakie żądania wysyłał, jakie dane wprowadzał. Pozwala to odtworzyć scenariusz błędu bez kontaktu z użytkownikiem.
Apple udostępnia wbudowany mechanizm zdalnego zbierania logów przez .logarchive, ale w aplikacjach produkcyjnych prawie zawsze używa się zewnętrznych serwisów. Android SDK zawiera Logcat, który jest dostępny zdalnie przez ADB, ale nie dla urządzeń użytkowników końcowych bez trybu debugowania.
Architektura remote logging składa się z trzech komponentów: klienckiego SDK na urządzeniu, który zbiera i buforuje logi, protokołu transportowego do wysyłania danych oraz serwera do przechowywania i wizualizacji.
| Komponent | Rola | Przykłady |
|---|---|---|
| SDK kliencki | Zbieranie, buforowanie, batching | Firebase SDK, Sentry Cocoa, Timber |
| Transport | Przesyłanie danych przez HTTPS | REST, gRPC, WebSocket |
| Serwer | Przechowywanie, indeksowanie, alerty | Sentry, Crashlytics, Datadog |
SDK kliencki buforuje logi w pamięci RAM i okresowo wysyła je na serwer partiami (batches). Jeśli urządzenie jest offline, logi są przechowywane w lokalnym pliku i wysyłane przy następnym połączeniu z siecią. Rozmiar bufora i interwał wysyłania są konfigurowalne: typowe wartości to 50 zdarzeń lub 30 sekund.
HTTPS REST — najpopularniejszy protokół dla remote logging. SDK serializuje logi do JSON i wysyła żądaniami POST na endpoint serwera. gRPC — alternatywa z binarną serializacją (Protocol Buffers), która jest o 30–40% bardziej kompaktowa niż JSON i szybsza na urządzeniach mobilnych z niestabilnym połączeniem. WebSocket jest używany do logowania w czasie rzeczywistym podczas debugowania, ale rzadko w produkcji ze względu na zużycie energii.
Firebase Crashlytics — darmowy serwis Google do zbierania raportów awarii i niestandardowych logów. Jest wbudowany w Firebase SDK i nie wymaga osobnego serwera. Crashlytics automatycznie zbiera stack trace, stan urządzenia, wersję systemu operacyjnego i otwarte ekrany w momencie awarii.
Niestandardowe logi w Crashlytics dodaje się przez metodę log() — nie są one wysyłane na serwer natychmiast, ale przechowywane w buforze cyklicznym i dołączane do następnego raportu awarii. To kluczowa różnica w porównaniu z Sentry, gdzie każdy log jest osobnym zdarzeniem. Maksymalny rozmiar niestandardowych logów w Crashlytics to 64 KB na jedną awarię.
// Firebase Crashlytics — niestandardowe logi na Androidzie
import com.google.firebase.crashlytics.FirebaseCrashlytics
class CheckoutViewModel {
fun processPayment(amount: Double) {
FirebaseCrashlytics.getInstance()
.log("Payment started: amount=$amount")
try {
process(amount)
} catch (e: Exception) {
FirebaseCrashlytics.getInstance()
.recordException(e)
}
}
}
Firebase Crashlytics obsługuje setUserIdentifier do łączenia awarii z konkretnymi użytkownikami. Pomaga to określić, czy błąd jest masowy, czy dotyczy tylko jednego użytkownika. setCustomKey dodaje dowolne klucze do każdego raportu — wersję testu A/B, region, plan taryfowy.
Sentry — platforma do monitorowania błędów, która przechowuje nie tylko raporty awarii, ale także wszystkie niestandardowe zdarzenia (breadcrumbs) jako niezależne wpisy. W przeciwieństwie do Crashlytics, Sentry pozwala przeglądać sekwencję zdarzeń przed błędem w porządku chronologicznym — breadcrumbs są widoczne w interfejsie bez konieczności odtwarzania ich z logu awarii.
SDK Sentry automatycznie zbiera breadcrumbs dla zdarzeń systemowych: zmiany cyklu życia UIViewController (viewDidLoad, viewWillAppear), touches, kliknięcia przycisków, żądania HTTP przez URLSession. Wszystkie te zdarzenia są wyświetlane na osi czasu błędu wraz z niestandardowymi breadcrumbs. Dla Android analogicznie zbierane są lifecycle Activity i Fragment, zdarzenia onClick i żądania sieciowe przez OkHttp.
SDK Sentry dla iOS i Android automatycznie zbiera breadcrumbs zdarzeń UI: touches, nawigacja, lifecycle. Programista może dodawać niestandardowe breadcrumbs przez addBreadcrumb() z określeniem typu, kategorii i poziomu. Sentry obsługuje distributed tracing: logger łączy breadcrumbs na kliencie z żądaniami na backendzie przez identyfikator trace.
import Sentry
func trackCartEvent(action: String, itemId: String) {
let crumb = Breadcrumb()
crumb.level = .info
crumb.category = "cart"
crumb.message = "Cart \(action): \(itemId)"
crumb.data = ["action": action, "item_id": itemId]
SentrySDK.addBreadcrumb(crumb)
}
Logcat — standardowy system logowania Android, dostępny przez Android Debug Bridge (ADB). Logcat zbiera wszystkie komunikaty systemowe i aplikacyjne, podzielone na poziomy (V, D, I, W, E, F) i tagi. Zdalny dostęp do Logcat działa przez ADB przez USB lub Wi-Fi, ale tylko dla urządzeń w trybie debugowania — aplikacje produkcyjne na urządzeniach bez połączenia USB są niedostępne.
Do zdalnego logowania w produkcji na Android używa się alternatyw: Logcat sam w sobie nie umie wysyłać logów na serwer. Jego rolą jest lokalna diagnostyka. Istnieją jednak nakładki (Timber, LogcatLive), które przekazują komunikaty do Firebase lub Sentry, zachowując znajome API Log.d / Log.e. Timber pozwala przełączać handlery bez zmiany kodu aplikacji — drzewko debugowe pisze do Logcat, drzewko release wysyła na serwer z batchowaniem i kompresją.
Batching — grupowanie wielu logów w jedno żądanie HTTP w celu oszczędzania transferu i baterii. Zamiast 50 osobnych żądań POST, SDK wysyła jedną tablicę JSON. Typowe strategie: wysyłanie według harmonogramu (co 30 sekund), według liczby (co 50 zdarzeń) lub według zdarzenia (tylko przy krytycznym błędzie).
Dla aplikacji z milionami użytkowników objętość logów może osiągać terabajty dziennie. Batching zmniejsza liczbę żądań 10–50 razy i obniża obciążenie serwera. Sentry używa kompresji gzip na poziomie transportu, co dodatkowo zmniejsza objętość danych o 60–70%.
// Prosta implementacja batchingu na Androida
class LogBatcher {
private val buffer = mutableListOf<LogEvent>()
private val maxSize = 50
private val intervalMs = 30_000L
fun append(event: LogEvent) {
buffer.add(event)
if (buffer.size >= maxSize) flush()
}
suspend fun flush() {
val batch = buffer.toList()
buffer.clear()
sendToServer(batch)
}
}
gzip — standardowa metoda kompresji dla przesyłania logów przez HTTP. SDK Sentry i Crashlytics automatycznie kompresują treść żądania przed wysłaniem. Deduplikacja — usuwanie powtarzających się komunikatów po stronie klienta: jeśli to samo zdarzenie występuje 100 razy na sekundę, SDK wysyła je raz z polem count = 100.
Najczęstszym błędem jest logowanie danych wrażliwych. Remote logging SDK przesyła dane na serwer, a jeśli programista przypadkowo zaloguje hasło, token lub email użytkownika, dane te trafiają do infrastruktury chmurowej. Zawsze używaj filtracji PII (Personally Identifiable Information) na poziomie SDK: Sentry ma wbudowany beforeSend-hook do czyszczenia danych przed wysłaniem.
Drugim częstym problemem jest nadmierne logowanie. Jeśli każde poruszenie palcem jest wysyłane na serwer, objętość danych rośnie wykładniczo, a koszty serwerowe również. Określ budżet na logi: nie więcej niż 1–5 zdarzeń na użytkownika na minutę w produkcji. Logi debugowania wysyłaj tylko z flagą włączaną dla konkretnych urządzeń.
Trzecim błędem jest ignorowanie scenariusza offline. Jeśli SDK traci logi przy braku sieci i nie odtwarza ich po ponownym połączeniu, remote logging jest bezużyteczny dla użytkowników z niestabilnym połączeniem. Wszystkie SDK (Firebase, Sentry) automatycznie buforują logi w lokalnym pliku i wysyłają przy pojawieniu się sieci, ale to ustawienie należy sprawdzić.
Często zadawane pytania
Crash reporting zbiera tylko informacje o awariach aplikacji. Remote Logging zbiera wszystkie zdarzenia: niestandardowe logi, breadcrumbs, metryki wydajności, zdarzenia UI. Crash reporting jest podzbiorem remote logging, a nie jego alternatywą.
Crashlytics jest darmowy i wystarczający do podstawowych raportów awarii. Sentry jest lepszy, jeśli potrzebujesz breadcrumbs, distributed tracing, niestandardowych dashboardów i elastycznych alertów. Dla projektów enterprise z wymogami compliance Sentry jest dostępny w wersji self-hosted.
Używaj poziomów logowania: logi debug/info wysyłaj tylko z urządzenia programisty przez flagę isDebuggable. Pozostałe poziomy (warn, error) filtruj przez beforeSend-hook, usuwając pola zawierające PII. Określ maksymalny rozmiar logu na sesję.
Logcat nie obsługuje zdalnego wysyłania na serwer. Do remote logging na Android używaj Timber do przekazywania do Firebase lub Sentry, a Logcat zostaw do debugowania przez USB. Timber zastępuje Android Log API i dodaje sadzone drzewa.
Do 50 zdarzeń na minutę na urządzenie nie wpływa zauważalnie na zużycie baterii, jeśli używany jest batching (wysyłanie partiami, a nie pojedynczo). Przy 200+ zdarzeniach na minutę Wi-Fi/modem będzie stale aktywny — bateria rozładowuje się o 15–25% szybciej.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również