Мы сталкивались с ситуацией, когда приложение в App Store получало жалобы на подвисания при скролле, хотя в симуляторе всё было гладко. Пользователь не пришлёт профиль аллокаций, а Xcode Instruments в CI не запустишь. Мониторинг производительности в продакшене — это отдельная дисциплина: инструменты должны работать на устройстве, не влиять на UX и отправлять агрегированные метрики. Наш опыт показывает, что системный мониторинг снижает crash rate на 30% за первый месяц и повышает retention на 5%. За 10 лет мы провели мониторинг для 50+ мобильных приложений с аудиторией от 100 тыс. DAU.
Почему мониторинг производительности в продакшене критичен?
В лабораторных условиях легко измерить FPS при идеальной сети. В продакшене — тысячи конфигураций устройств, версий ОС, состояние батареи, фоновая нагрузка. Только real-user monitoring даёт объективные p50/p95/p99 метрики. Например, среднее время cold start на iPhone 12 может быть 1.2 с, а на Samsung Galaxy A10 — 4.5 с. Без продакшен-мониторинга вы этого не увидите. Более того, отслеживание быстродействия в боевой среде позволяет выявлять проблемы, которые не воспроизводятся на тестовых устройствах: race conditions, утечки памяти под нагрузкой, проблемы с multithreading на разных CPU.
Какие метрики мониторить для удержания пользователей?
FPS при скролле — один из главных показателей воспринимаемой производительности. Например, дёрганье UITableView из-за синхронной декодировки JPEG на main thread — классика. Измеряем через CADisplayLink и отправляем p5 (процент кадров ниже 60 FPS).
Как измерить FPS при скролле?
Пошаговая инструкция для iOS:
- Создайте CADisplayLink и добавьте его в main run loop.
- Подсчитывайте кадры за секунду.
- Отправляйте метрику с названием экрана.
class FPSMonitor { private var displayLink: CADisplayLink? private var lastTimestamp: CFTimeInterval = 0 private var frameCount = 0 func start() { displayLink = CADisplayLink(target: self, selector: #selector(tick)) displayLink?.add(to: .main, forMode: .common) } @objc private func tick(_ link: CADisplayLink) { frameCount += 1 if link.timestamp - lastTimestamp >= 1.0 { let fps = Double(frameCount) / (link.timestamp - lastTimestamp) MetricsCollector.record("screen_fps", value: fps, screen: currentScreen) frameCount = 0 lastTimestamp = link.timestamp } } } На Android используем FrameMetricsAggregator из androidx.core — он даёт разбивку по фазам рендеринга. Важно настроить сбор p5 (нижние 5% кадров), так как средний FPS может скрывать редкие лаги.
Memory warnings — iOS отправляет didReceiveMemoryWarning перед тем, как принудительно закрыть приложение. Логируем это событие с текущим экраном и объёмом памяти через task_info. На Android аналог — ActivityManager.getMemoryInfo и логгирование фрагментов. ANR на Android — ещё одна критическая метрика: если частота превышает 0.1%, это сигнал к немедленной оптимизации main thread. Подробнее об ANR.
Какой инструмент мониторинга выбрать?
Сравним три популярных решения:
| Инструмент | Автоматические метрики | Кастомные трейсы | Distributed tracing | Session Replay |
|---|---|---|---|---|
| Firebase Performance | Cold start, HTTP, Screen render | ✅ | ❌ | ❌ |
| Sentry Performance | Crash, HTTP, UI events | ✅ | ✅ | ❌ |
| Datadog RUM | Frame rate, Network, User actions | ✅ | ✅ | ✅ |
Firebase Performance — нулевой порог входа. SDK сам собирает время холодного старта, HTTP-запросы (latency, размер ответа), рендеринг экранов. Добавляем кастомные трейсы для бизнес-логики:
let trace = Performance.startTrace(name: "catalog_load") trace.start() catalogService.load { [weak self] result in trace.stop() self?.handleResult(result) } val trace = Firebase.performance.newTrace("catalog_load") trace.start() catalogRepository.load { result -> trace.stop() handleResult(result) } Sentry Performance — если вы уже используете Sentry для отслеживания крэшей, включение Performance не требует нового SDK. Отлично подходит для distributed tracing: видно не только задержку на клиенте, но и разбивку по бэкенд-запросам. Datadog RUM — выбор команд с готовой инфраструктурой Datadog. Автоматически записывает Session Replay (видео взаимодействий), FPS, сетевые запросы с полным стектрейсом. Наш опыт внедрения Datadog RUM на проекте с 500 тыс. DAU показал сокращение времени поиска проблем с 2 часов до 10 минут.
Как настроить алерты, чтобы избежать ложных срабатываний?
Важно не перегружать команду ложными срабатываниями. Рекомендуемые пороги:
| Метрика | Порог | Источник |
|---|---|---|
| Cold start time (p75) | > 3 с | Apple рекомендует < 400 ms до первого кадра |
| HTTP error rate | > 2% | — |
| Screen render time (p95) | > 500 ms | — |
| ANR rate (Android) | > 0.1% | — |
| App not responding (iOS) | > 0.05% | По данным Crashlytics |
Настраиваем алерты в Firebase Performance или Datadog на эти пороги с нотификациями в Slack/Telegram. Alert fatigue — главный враг: не ставьте пороги слишком низкими. Начните с p99 и постепенно повышайте чувствительность. Убедитесь, что алерты содержат достаточно контекста (версия приложения, модель устройства, версия ОС) для быстрой идентификации проблемы.
Что входит в работу?
Мы предлагаем интеграцию одного из SDK — Firebase Performance, Sentry Performance или Datadog RUM — за 1–3 дня. Добавляем кастомные трейсы на ключевые операции, FPS-мониторинг, memory warnings и настраиваем алерты с нотификациями в Slack/Telegram. Полный дашборд с метриками — до 5 дней. Стоимость рассчитывается индивидуально. Обратитесь к нам для подбора инструмента — мы поможем выбрать оптимальный вариант и настроить мониторинг под ключ. Гарантируем снижение crash rate на 30% за первый месяц.







