Мониторинг продуктивності мобільного приложення в production
Xcode Instruments у CI не запустиш, і користувач не пришле профіль алокацій. Мониторинг продуктивності в production — це окреме завдання з інструментами, які працюють на пристрої, не заважають користувачу та відправляють агреговані метрики на сервер.
Що вимірюємо та якими інструментами
Firebase Performance Monitoring — нульовий поріг входу. SDK автоматично вимірює: час cold start, HTTP-запити (latency, payload size, success rate), час рендерингу екранів. Додаємо кастомні трейси для будь-якого коду:
// iOS — кастомний трейс для критичної операції
let trace = Performance.startTrace(name: "catalog_load")
trace.start()
catalogService.load { [weak self] result in
trace.stop() // метрика йде в Firebase
self?.handleResult(result)
}
// Android
val trace = Firebase.performance.newTrace("catalog_load")
trace.start()
catalogRepository.load { result ->
trace.stop()
handleResult(result)
}
Sentry Performance — якщо Sentry вже використовується для крешів, Performance Monitoring включається без додат. SDK. Дає distributed tracing: видно не тільки час операції на клієнті, але й розбивку за API-запитами, які вона породжує.
Datadog RUM — для команд з існуючою Datadog-інфраструктурою. Автоматично трекує Session Replay (запис взаємодій користувача), Frame Rate, Network requests з full stack trace.
Метрики, які реально впливають на retention
FPS у скролле — один із ключових показників сприйманої продуктивності. UITableView дергається при швидкому скролі через синхронну декодировку JPEG на main thread — класична проблема. Вимірюємо через CADisplayLink та відправляємо p5 (процент кадрів нижче 60fps) в аналітику:
// Простий FPS-монітор
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 дає детальну розбивку за фазами рендерингу.
Memory warnings — iOS відправляє didReceiveMemoryWarning перед тим як убити приложение. Логуємо цю подію з поточним екраном та обсягом allocated memory через task_info:
NotificationCenter.default.addObserver(
forName: UIApplication.didReceiveMemoryWarningNotification,
object: nil, queue: .main
) { _ in
Analytics.logEvent("memory_warning", parameters: [
"current_screen": AppRouter.currentScreen,
"memory_mb": memoryUsageMB()
])
}
Алерти та пороги
Настроюємо алерти в Firebase Performance або Datadog на:
- Cold start time > 3s (p75) — Apple рекомендує < 400ms до першого кадра
- HTTP error rate > 2%
- Screen render time > 500ms (p95)
- ANR rate (Android) > 0.1%
- App not responding (iOS watchdog kills) — через crash rate Crashlytics
Головне: не ставити алерти на занадто низькі пороги — alert fatigue вбиває реакцію на реальні проблеми.
Що входить у роботу
- Інтеграція Firebase Performance / Sentry Performance / Datadog RUM
- Кастомні трейси на ключові операції (завантаження, навігація, бізнес-процеси)
- FPS-мониторинг та memory monitoring
- Настройка алертів з нотифікаціями в Slack/Telegram
- Dashboard з ключовими метриками продуктивності
Строки
Інтеграція SDK + кастомні трейси + алерти: 1–3 дні. Вартість розраховується індивідуально.







