Remote Logging — это механизм отправки логов с мобильного устройства на удалённый сервер для централизованного анализа и мониторинга. В отличие от локального логирования, которое хранит данные на устройстве, удалённый сбор позволяет видеть ошибки и аномалии со всех устройств пользователей в реальном времени. По данным Sentry Resource Library, приложения с remote logging находят 92% production-багов за первый час после релиза против 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, но для production-приложений практически всегда используются сторонние сервисы. Android SDK включает Logcat, который доступен удалённо через ADB, но не для устройств конечных пользователей без отладки.
Архитектура remote logging состоит из трёх компонентов: клиентский SDK на устройстве, который собирает и буферизирует логи, транспортный протокол для отправки данных и сервер для хранения и визуализации.
| Компонент | Роль | Примеры |
|---|---|---|
| Клиентский SDK | Сбор, буферизация, батчинг | Firebase SDK, Sentry Cocoa, Timber |
| Транспорт | Передача данных через HTTPS | REST, gRPC, WebSocket |
| Сервер | Хранение, индексация, алерты | Sentry, Crashlytics, Datadog |
Клиентский SDK буферизирует логи в оперативной памяти и периодически сбрасывает их на сервер пачками (batches). Если устройство офлайн, логи сохраняются в локальном файле и отправляются при следующем подключении к сети. Размер буфера и интервал отправки настраиваются: типичные значения — 50 событий или 30 секунд.
HTTPS REST — самый распространённый протокол для remote logging. SDK сериализует логи в JSON и отправляет POST-запросами на endpoint сервера. gRPC — альтернатива с бинарной сериализацией (Protocol Buffers), которая на 30–40% компактнее JSON и быстрее на мобильных устройствах с нестабильным соединением. WebSocket используется для реалтайм-логирования в отладке, но редко в production из-за энергопотребления.
Firebase Crashlytics — бесплатный сервис Google для сбора краш-репортов и кастомных логов. Он встроен в Firebase SDK и не требует отдельного сервера. Crashlytics автоматически собирает stack trace, состояние устройства, версию ОС и открытые экраны на момент падения.
Кастомные логи в Crashlytics добавляются через метод log() — они не отправляются на сервер немедленно, а сохраняются в кольцевом буфере и прикрепляются к следующему краш-репорту. Это ключевое отличие от Sentry, где каждый лог — отдельное событие. Максимальный объём кастомных логов в Crashlytics — 64 КБ на один краш.
// 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 добавляет произвольные ключи к каждому репорту — версию А/B-теста, регион, тарифный план.
Sentry — платформа для мониторинга ошибок, которая хранит не только краш-репорты, но и все кастомные события (breadcrumbs) как самостоятельные записи. В отличие от Crashlytics, Sentry позволяет просматривать последовательность событий до ошибки в хронологическом порядке — breadcrumbs видны в интерфейсе без необходимости восстанавливать их из лога краша.
Sentry SDK автоматически собирает breadcrumbs для системных событий: изменения жизненного цикла UIViewController (viewDidLoad, viewWillAppear), touches, нажатия на кнопки, HTTP-запросы через URLSession. Все эти события отображаются в таймлайне ошибки вместе с кастомными breadcrumbs. Для Android аналогично собираются lifecycle Activity и Fragment, onClick-события и сетевые запросы через OkHttp.
Sentry SDK для iOS и Android автоматически собирает breadcrumbs UI-событий: touches, navigation, lifecycle. Разработчик может добавлять кастомные breadcrumbs через addBreadcrumb() с указанием типа, категории и уровня. Sentry поддерживает distributed tracing: логгер связывает breadcrumbs на клиенте с запросами на бэкенде через 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, но только для устройств в режиме отладки — production-приложения на устройствах без USB-подключения недоступны.
Для remote logging в production на Android используются альтернативы: Logcat сам по себе не умеет отправлять логи на сервер. Его роль — локальная диагностика. Но существуют обёртки (Timber, LogcatLive) которые форвардят сообщения в Firebase или Sentry, сохраняя привычный API Log.d / Log.e. Timber позволяет переключать обработчики без изменения кода приложения — debug-дерево пишет в Logcat, release-дерево отправляет на сервер с батчингом и сжатием.
Батчинг — группировка нескольких логов в один HTTP-запрос для экономии трафика и батареи. Вместо 50 отдельных POST-запросов SDK отправляет один массив JSON. Типичные стратегии: отправка по расписанию (каждые 30 секунд), по количеству (каждые 50 событий) или по событию (только при критической ошибке).
Для приложений с миллионами пользователей объём логов может достигать терабайт в день. Батчинг сокращает количество запросов в 10–50 раз и снижает нагрузку на сервер. Sentry использует сжатие gzip на транспортном уровне, что дополнительно уменьшает объём данных на 60–70%.
// Простая реализация батчинга на 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 передаёт данные на сервер, и если разработчик случайно логирует пароль, токен или email пользователя, эти данные оказываются в облачной инфраструктуре. Всегда используйте фильтрацию PII (Personally Identifiable Information) на уровне SDK: Sentry имеет встроенный beforeSend-хук для очистки данных перед отправкой.
Вторая распространённая проблема — чрезмерное логирование. Если каждое движение пальца отправляется на сервер, объём данных растёт экспоненциально, а серверные расходы — тоже. Определите бюджет на логи: не более 1–5 событий на пользователя в минуту в production. Debug-логи отправляйте только с флагом, который включается для конкретных устройств.
Третья ошибка — игнорирование офлайн-сценария. Если SDK теряет логи при отсутствии сети и не восстанавливает их при reconnect, remote logging бесполезен для пользователей с нестабильным соединением. Все SDK (Firebase, Sentry) автоматически кэшируют логи в локальный файл и отправляют при появлении сети, но эту настройку нужно проверять.
Часто задаваемые вопросы
Crash reporting собирает только информацию о падениях приложения. Remote Logging собирает все события: кастомные логи, breadcrumbs, метрики производительности, UI-события. Crash reporting — это подмножество remote logging, а не его альтернатива.
Crashlytics — бесплатный и достаточный для базовых краш-репортов. Sentry лучше, если нужны breadcrumbs, distributed tracing, кастомные дашборды и гибкие алерты. Для enterprise-проектов с compliance-требованиями Sentry доступен в self-hosted версии.
Используйте уровни логирования: debug/info логи отправляйте только с устройства разработчика через флаг isDebuggable. Остальные уровни (warn, error) фильтруйте через beforeSend-хук, удаляя поля, содержащие PII. Определите максимальный размер лога на сессию.
Logcat не поддерживает удалённую отправку на сервер. Для remote logging на Android используйте Timber для форвардинга в Firebase или Sentry, а Logcat оставьте для отладки через USB. Timber заменяет Android Log API и добавляет plantable деревья.
До 50 событий в минуту на устройство не влияют на расход батареи заметно, если используется батчинг (отправка пачками, а не по одному). При 200+ событиях в минуту Wi-Fi/модем будет активен постоянно — батарея садится на 15–25% быстрее.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также