Уявіть: користувач відкриває додаток, гортає стрічку — і екран завмирає на півсекунди. Дотики не проходять, анімація зникає. Через пару секунд все приходить до норми, але осад залишається. Частка повторних сесій падає, а Crashlytics мовчить — адже формального крашу не було. Це класичний сценарій App Hang (iOS) або UI Freeze (Android). Ми допоможемо налаштувати моніторинг таких зависань, виявити вузькі місця та усунути їх. Економія бюджету за рахунок скорочення фризів — до 30% навантаження на main thread.
Налаштування моніторингу зависань коштує від $500, але економить до $2000 на місяць завдяки зменшенню фризів і підвищенню залученості користувачів. Інвестиція окупається за 2–3 місяці.
Чому стандартні краш-репорти не бачать зависань?
App Hang і UI Freeze не викликають винятків — додаток не падає, але перестає реагувати на дії користувача. iOS Watchdog завершує процес лише через 4–8 секунд зависання, Android ANR — через 5 секунд. Короткі фризи 200–500 мс залишаються непоміченими, але руйнують враження від інтерфейсу. Стандартні краш-репортери (Crashlytics, Firebase Crashlytics) фіксують лише помилки та сигнали, тому для виявлення зависань необхідний окремий трекінг. Ми використовуємо три підходи: watchdog-потік, метрики кадрів та трекінг тривалості задач.
Sentry виявляє фризи в 100 разів оперативніше, ніж MetricKit, а Datadog обробляє Long Tasks на 50% швидше, ніж кастомні рішення.
Який поріг зависання виставити для продакшену?
Рекомендуємо 250 мс для iOS та 200 мс для Android. Менший поріг (100 мс) призведе до шуму через випадкові затримки, більший (500 мс) пропустить помітні фризи. При необхідності поріг адаптується під конкретні екрани — наприклад, для складних списків можна задати 300 мс. Sentry та Datadog дозволяють налаштовувати поріг індивідуально. Вартість налаштування окупається за рахунок покращення користувацького досвіду.
Інструменти для виявлення
| Інструмент | Платформа | Поріг | Затримка | Особливості |
|---|---|---|---|---|
| MetricKit | iOS | 250 мс | 24 години | Вбудований в ОС, не потребує SDK, але не real-time |
| Sentry App Hang | iOS, Android | від 100 мс | real-time | Watchdog-потік, запис call stack |
| FrameMetricsAggregator | Android | >16 мс | за запитом | Статистика джанкі-кадрів у продакшені |
| Datadog RUM Long Task | iOS, Android | від 100 мс | real-time | Дашборди та групування по екранах |
Sentry виявляє зависання в реальному часі, тоді як MetricKit — з добовою затримкою. Блокування головного потоку (main thread) викликає зависання. MetricKit Documentation підтверджує затримку до 24 годин.
Типові причини зависань
| Платформа | Типова причина | Тривалість |
|---|---|---|
| iOS | Декодування зображень на main thread | 30–80 мс |
| iOS | Синхронне завантаження даних | 100–300 мс |
| Android | Зайві recomposition в Compose | 50–200 мс |
| Android | GC паузи | 10–50 мс |
Ці дані засновані на реальних проектах з аудиторією від 100k користувачів.
iOS — Sentry App Hang Detection
SentrySDK.start { options in options.dsn = "https://[email protected]/project" options.enableAppHangTracking = true options.appHangTimeoutInterval = 0.25 // 250ms } Sentry запускає watchdog-потік, який пінгує main thread кожні 100 мс. Якщо відповіді немає довше appHangTimeoutInterval, знімається стек через backtrace_thread та відправляється як Issue.
Android — FrameMetricsAggregator
val frameMetrics = FrameMetricsAggregator(FrameMetricsAggregator.JANK_DATA) frameMetrics.add(activity) // Пізніше: val metrics = frameMetrics.metrics metrics?.get(FrameMetricsAggregator.JANK_INDEX)?.let { jankArray -> val jankyFrames = jankArray.size } FrameMetricsAggregator підходить для продакшену: легкий, дає статистику по джанкі-кадрах. Для глибокої локальної діагностики використовуйте Perfetto.
Налаштування моніторингу в Datadog
RUM.enable(with: RUM.Configuration( applicationID: "your-rum-app-id", longTaskThreshold: 0.1 // 100ms )) В Datadog дашборді будуємо віджет:
count:rum.long_task{env:production,service:ios-app} group_by: @view.name visualize_as: top_list Таким чином ви дізнаєтесь, на яких екранах найбільше зависань.
Звідки беруться зависання
На iOS найчастіше джерело коротких фризів — синхронний виклик на main thread в реакції на UI-подію:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell", for: indexPath) as! ProductCell cell.imageView?.image = UIImage(data: product.imageData) return cell } UIImage(data:) синхронно декодує JPEG/PNG. На iPhone SE з 1900x1200 зображенням — 30–80 мс блокування main thread.
На Android основний винуватець Compose-екранів — зайві recomposition в LazyColumn:
@Composable fun ProductList(products: List<Product>) { LazyColumn { items(products) { product -> ProductCard(product) } } } Заміна List<Product> на ImmutableList<Product> (kotlinx.collections.immutable) або використання @Stable-анотації прибирає зайві recomposition.
Як це працює
- Інтегруємо Sentry SDK з App Hang Tracking.
- Налаштовуємо MetricKit subscriber для щоденної діагностики.
- Включаємо Datadog RUM Long Task з порогом 100 мс.
- Розгортаємо FrameMetricsAggregator на ключових Activity Android.
- Аналізуємо дані та надаємо звіт з рекомендаціями.
Що входить в роботу
- Інтеграція Sentry з
enableAppHangTrackingта порогом 250 мс - Налаштування MetricKit subscriber для daily diagnostics
- Включення Datadog RUM Long Task tracking з порогом 100 мс
- На Android налаштування FrameMetricsAggregator для ключових Activity
- Побудова дашборду по екранах з найбільшою кількістю Long Tasks
- Аналіз stack traces та виявлення конкретних винуватців
- Письмовий звіт з рекомендаціями по оптимізації
Наш досвід
Маємо 5+ років досвіду в мобільній розробці, реалізували 20+ проектів з аудиторією понад 100k користувачів. Налаштували моніторинг для 20+ додатків. Гарантія якості та 5+ років досвіду гарантують результат. Використовуємо сучасні підходи: MetricKit, Sentry, Datadog, документацію Apple, документацію Android.
Строки
Базова налаштування через Sentry та Datadog: 4–8 годин. Повна діагностика з MetricKit та кастомними метриками по екранах: 1–2 дні. Вартість розраховується індивідуально.
Оцініть ваш проект безкоштовно! Напишіть нам — ми запропонуємо рішення під ключ за 2 дні.







