Remote Logging е механизъм за изпращане на логове от мобилно устройство до отдалечен сървър за централизиран анализ и мониторинг. За разлика от локалното логване, което съхранява данни на устройството, отдалеченото събиране позволява да виждате грешки и аномалии от всички устройства на потребителите в реално време. Според Sentry Resource Library, приложенията с remote logging откриват 92% от производствените бъгове в първия час след пускане, срещу 15% при използване само на краш репорти. Това е задължителен инструмент за всеки екип за мобилно разработване: Firebase Crashlytics, Sentry и Datadog предоставят готови SDK за iOS и Android.
Основни неща
Remote Logging е процес на събиране на логове от отдалечени устройства и изпращането им до централен сървър за анализ. В контекста на мобилното разработване, remote logging включва не само краш репорти (crash reporting), но също така персонализирани събития, breadcrumbs, метрики за производителност и потребителски сценарии.
Основната разлика между remote logging и crash reporting е проактивността. Crash reporting събира само данни за падания на приложението, които вече са се случили. Remote logging събира последователността от събития преди краша: кои екрани е отварял потребителят, какви заявки е правил, какви данни е въвеждал. Това позволява да се възпроизведе сценарият на грешката без комуникация с потребителя.
Apple предоставя вграден механизъм за отдалечено събиране на логове чрез .logarchive, но за производствени приложения почти винаги се използват услуги на трети страни. Android SDK включва Logcat, който е достъпен отдалечено чрез ADB, но не за устройства на крайни потребители без режим на отстраняване на грешки.
Архитектурата на remote logging се състои от три компонента: клиентски SDK на устройството, който събира и буферира логове, транспортен протокол за изпращане на данни и сървър за съхранение и визуализация.
| Компонент | Роля | Примери |
|---|---|---|
| Клиентски SDK | Събиране, буфериране, batching | Firebase SDK, Sentry Cocoa, Timber |
| Транспорт | Предаване на данни чрез HTTPS | REST, gRPC, WebSocket |
| Сървър | Съхранение, индексиране, аларми | Sentry, Crashlytics, Datadog |
Клиентският SDK буферира логове в RAM паметта и периодично ги изпраща на сървъра на партиди (batches). Ако устройството е офлайн, логовете се запазват в локален файл и се изпращат при следващото свързване към мрежата. Размерът на буфера и интервалът на изпращане са конфигурируеми: типични стойности са 50 събития или 30 секунди.
HTTPS REST — най-разпространеният протокол за remote logging. SDK сериализира логове в JSON и ги изпраща чрез POST заявки към endpoint на сървъра. gRPC — алтернатива с двоична сериализация (Protocol Buffers), която е с 30–40% по-компактна от JSON и по-бърза на мобилни устройства с нестабилна връзка. WebSocket се използва за логване в реално време при отстраняване на грешки, но рядко в производство поради консумация на енергия.
Firebase Crashlytics — безплатната услуга на Google за събиране на краш репорти и персонализирани логове. Тя е вградена в Firebase SDK и не изисква отделен сървър. Crashlytics автоматично събира stack trace, състояние на устройството, версия на операционната система и отворени екрани в момента на краша.
Персонализираните логове в Crashlytics се добавят чрез метода log() — те не се изпращат веднага до сървъра, а се съхраняват в пръстеновиден буфер и се прикрепят към следващия краш репорт. Това е ключовата разлика от Sentry, където всеки лог е отделно събитие. Максималният обем на персонализирани логове в Crashlytics е 64 KB на краш.
// Firebase Crashlytics — персонализирани логове на Android
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 поддържа setUserIdentifier за свързване на крашове с конкретни потребители. Това помага да се определи дали бъгът е масов или засяга само един потребител. setCustomKey добавя произволни ключове към всеки репорт — версия на A/B тест, регион, тарифен план.
Sentry — платформа за мониторинг на грешки, която съхранява не само краш репорти, но и всички персонализирани събития (breadcrumbs) като независими записи. За разлика от Crashlytics, Sentry позволява да преглеждате последователността от събития преди грешката в хронологичен ред — breadcrumbs са видими в интерфейса без необходимост от възстановяване от краш лога.
Sentry SDK автоматично събира breadcrumbs за системни събития: промени в жизнения цикъл на UIViewController (viewDidLoad, viewWillAppear), докосвания, кликвания върху бутони, HTTP заявки чрез URLSession. Всички тези събития се показват на времевата линия на грешката заедно с персонализирани breadcrumbs. За Android по подобен начин се събират жизнен цикъл на Activity и Fragment, onClick събития и мрежови заявки чрез OkHttp.
Sentry SDK за iOS и Android автоматично събира breadcrumbs на UI събития: докосвания, навигация, жизнен цикъл. Разработчикът може да добавя персонализирани breadcrumbs чрез addBreadcrumb() с посочване на тип, категория и ниво. Sentry поддържа distributed tracing: логърът свързва breadcrumbs на клиента със заявки към backend чрез trace ID.
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 — стандартната система за логване на Android, достъпна чрез Android Debug Bridge (ADB). Logcat събира всички системни и приложни съобщения, разделени по нива (V, D, I, W, E, F) и тагове. Отдалеченият достъп до Logcat работи чрез ADB чрез USB или Wi-Fi, но само за устройства в режим на отстраняване на грешки — производствени приложения на устройства без USB връзка не са достъпни.
За отдалечено логване в производство на Android се използват алтернативи: Logcat сам по себе си не може да изпраща логове до сървър. Неговата роля е локална диагностика. Но съществуват обвивки (Timber, LogcatLive), които препращат съобщения към Firebase или Sentry, запазвайки познатото API Log.d / Log.e. Timber позволява превключване на handler-и без промяна на кода на приложението — debug дървото пише в Logcat, release дървото изпраща до сървъра с batching и компресия.
Batching — групиране на няколко лога в една HTTP заявка за пестене на трафик и батерия. Вместо 50 отделни POST заявки, SDK изпраща един JSON масив. Типични стратегии: изпращане по график (на всеки 30 секунди), по брой (на всеки 50 събития) или по събитие (само при критична грешка).
За приложения с милиони потребители, обемът на логовете може да достигне терабайти на ден. Batching намалява броя на заявките 10–50 пъти и намалява натоварването на сървъра. Sentry използва gzip компресия на транспортно ниво, което допълнително намалява обема на данните с 60–70%.
// Проста имплементация на batching на Android
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 — стандартният метод за компресия при HTTP предаване на логове. SDK на Sentry и Crashlytics автоматично компресират тялото на заявката преди изпращане. Дедупликация — премахване на повтарящи се съобщения от страна на клиента: ако едно и също събитие се улавя 100 пъти в секунда, SDK го изпраща веднъж с поле count = 100.
Най-честата грешка — логване на чувствителни данни. Remote logging SDK предава данни на сървъра и ако разработчик случайно логне парола, токен или имейл на потребител, тези данни попадат в облачната инфраструктура. Винаги използвайте PII (Лична идентифицираща информация) филтрация на ниво SDK: Sentry има вграден beforeSend-hook за почистване на данни преди изпращане.
Вторият често срещан проблем — прекомерно логване. Ако всяко движение на пръста се изпраща до сървъра, обемът на данните расте експоненциално, а разходите за сървъра също. Определете бюджет за логове: не повече от 1–5 събития на потребител на минута в производство. Debug логове изпращайте само с флаг, който се включва за конкретни устройства.
Третата грешка — игнориране на офлайн сценария. Ако SDK губи логове при липса на мрежа и не ги възстановява при повторно свързване, remote logging е безполезен за потребители с нестабилна връзка. Всички SDK (Firebase, Sentry) автоматично кешират логове в локален файл и ги изпращат при поява на мрежа, но тази настройка трябва да се провери.
Често задавани въпроси
Crash reporting събира само информация за падания на приложението. Remote Logging събира всички събития: персонализирани логове, breadcrumbs, метрики за производителност, UI събития. Crash reporting е подмножество на remote logging, а не негова алтернатива.
Crashlytics е безплатен и достатъчен за основни краш репорти. Sentry е по-добър, ако имате нужда от breadcrumbs, distributed tracing, персонализирани табла и гъвкави аларми. За enterprise проекти с изисквания за съответствие, Sentry е достъпен в self-hosted версия.
Използвайте нива на логване: изпращайте debug/info логове само от устройството на разработчика чрез флага isDebuggable. Останалите нива (warn, error) филтрирайте чрез beforeSend-hook, премахвайки полета, съдържащи PII. Определете максималния размер на лога на сесия.
Logcat не поддържа отдалечено изпращане до сървър. За remote logging на Android използвайте Timber за препращане към Firebase или Sentry, а Logcat оставете за отстраняване на грешки чрез USB. Timber замества Android Log API и добавя засадими дървета.
До 50 събития на минута на устройство не влияят осезаемо на консумацията на батерия, ако се използва batching (изпращане на партиди, а не поединично). При 200+ събития на минута Wi-Fi/модемът ще бъде постоянно активен — батерията се разрежда с 15–25% по-бързо.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също