Мониторинг стабильности мобильного приложения в продакшене
Crash-free rate 99.2% звучит хорошо, пока не посчитать: при 100 000 DAU это 800 крашей в день. Без инструментов мониторинга команда узнаёт о проблеме из отзывов в App Store — то есть с задержкой в несколько часов после того, как сотни пользователей уже столкнулись с ошибкой.
Что мониторим
Крэши и ошибки
Основной инструмент — Firebase Crashlytics. Автоматически перехватывает fatal и non-fatal исключения, группирует по стектрейсу, показывает затронутых пользователей и сессии. Ключевые метрики для ежедневного контроля:
- Crash-free users (не sessions) — реальная картина по пользователям
- Velocity alerts — Crashlytics умеет присылать уведомление, когда новый крэш затрагивает N% сессий за час
- Regression tracking — был крэш, закрыли, появился снова в новой версии
Для NDK/C++ компонентов нужно отдельно настраивать nativeSymbolUploadEnabled = true и загружать .so символы через Crashlytics CLI.
ANR и зависания (Android)
Google Play Console → Android Vitals → ANR rate. Пороговое значение Google — 0.47% ANR-rate, выше него приложение помечается как проблемное и снижается в поиске. ANR на главном потоке чаще всего означает блокирующий IO или синхронный запрос к базе данных в onCreate.
StrictMode в Debug-сборках помогает поймать такие места до продакшена:
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectNetwork()
.penaltyLog()
.build()
)
}
Производительность (iOS MetricKit)
MetricKit с iOS 14 доставляет агрегированные данные по диагностике: hang rate, crash rate, disk writes, launch time. Данные приходят раз в сутки в didReceive(_ payloads: [MXMetricPayload]). Для мониторинга launch time критично отслеживать applicationLaunchMetrics.histogrammedTimeToFirstDraw — деградация на 200ms уже влияет на удержание.
Нестандартные события
Firebase Crashlytics позволяет логировать non-fatal ошибки вручную — это важно для бизнес-критичных флоу:
// iOS: логируем ошибку оплаты как non-fatal
Crashlytics.crashlytics().record(error: paymentError)
Crashlytics.crashlytics().log("Payment failed at step: \(step)")
// Android
FirebaseCrashlytics.getInstance().recordException(exception)
FirebaseCrashlytics.getInstance().log("Checkout step: $step")
Так в Crashlytics появляются «мягкие» ошибки — пользователь не увидел крэша, но транзакция не прошла.
Алертинг
Настраиваем уведомления в Slack или Telegram через Crashlytics webhooks или Firebase Extensions. Минимальный набор алертов:
| Событие | Порог | Канал |
|---|---|---|
| Новый крэш в release-сборке | Любой | #crashes-mobile |
| Crash-free rate упал | < 99.5% за час | #incidents |
| ANR rate (Android) | > 0.3% | #android-ops |
| Velocity alert | > 0.1% сессий за 30 мин | #incidents (pager) |
Процесс работы
Первичная настройка: интеграция Crashlytics, настройка velocity alerts, подключение к Slack.
Ежедневный мониторинг: просмотр новых крэшей, сверка с Android Vitals и App Store Connect.
Регулярные отчёты: еженедельный срез crash-free rate в разрезе версий ОС и устройств.
Ориентиры по срокам
Первичная настройка полного мониторинга — 1–3 дня в зависимости от сложности проекта. Ongoing-мониторинг — обсуждается индивидуально.







