Ми стикалися з ситуацією, коли додаток в 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 мс до першого кадру |
| HTTP error rate | > 2% | — |
| Screen render time (p95) | > 500 мс | — |
| 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% за перший місяць.







