Настройка Real User Monitoring (RUM) для мобильного приложения
Синтетический мониторинг запускает скрипты в контролируемом окружении. RUM — это данные о том, что происходит с реальными пользователями на реальных устройствах в реальных сетях. Разница принципиальная: синтетика не покажет, что у пользователей Xiaomi Redmi Note 9 экран списка тормозит из-за overdraw в RecyclerView, а у пользователей на LTE в регионе — network timeout на 8-й секунде.
Что именно трекает RUM
Стандартный набор событий в мобильном RUM:
- View — переход на экран (открытие, закрытие, длительность)
- Action — тап, свайп, scroll, LongPress
- Resource — HTTP-запрос: URL, метод, статус, размер, latency
- Error — handled exception, unhandled exception, ANR, крэш
- Long Task — операция на main thread > 100ms (Android) / main runloop > 16ms (iOS)
Из всех событий самое диагностически ценное — Long Task в корреляции с View. Если Long Task в 250ms случается в момент перехода на экран оплаты, и это воспроизводится у 15% пользователей — перед вами конкретный перформанс-баг, а не «что-то иногда лагает».
Выбор инструмента
| Инструмент | Особенности | Самплинг |
|---|---|---|
| Datadog RUM | Полный стек mobile+server, W3C tracing | До 100%, гибкий |
| Sentry | Бесплатный tier, хорошие release comparisons | По умолчанию 100% |
| Firebase Performance | Бесплатно, только Google-экосистема | Автоматический |
| New Relic Mobile | Мощный NRQL, enterprise | До 100% |
Для большинства продуктов Firebase Performance — хороший старт (бесплатно, Zero-config для сети). Но как только нужна корреляция с серверными трейсами или кастомные бизнес-атрибуты — переходят на Datadog или Sentry.
Настройка на примере Datadog RUM
import DatadogRUM
RUM.enable(with: RUM.Configuration(
applicationID: "your-rum-app-id",
sessionSampleRate: 80, // 80% сессий
telemetrySampleRate: 20,
trackBackgroundEvents: false // не трекаем фоновые события
))
Параметр sessionSampleRate — первое, что нужно настроить под нагрузку. 100% сессий при миллионной DAU — это дорого. Стандартная практика: 100% для новых релизов первые 48 часов (ловим регрессии), потом снижаем до 20–30%.
Инструментация экранов вручную (SwiftUI)
struct ProductListView: View {
var body: some View {
List(products) { product in
ProductRow(product: product)
}
.trackRUMView(name: "ProductList")
}
}
Мониторинг конкретного сетевого запроса
// С URLSession + Datadog
let delegate = DDURLSessionDelegate()
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
Datadog автоматически инжектирует x-datadog-trace-id в каждый запрос через этот session — никаких дополнительных перехватчиков.
Типичная проблема: View duration искажается
Частый баг при настройке RUM — View закрывается слишком рано. Например, в UIKit без явного вызова stopView агент закрывает View при viewWillDisappear, но если контроллер показывает bottom sheet поверх себя — View закроется и откроется заново, создав дублирующую запись. Решение:
// iOS — явное управление View lifecycle
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
RUM.monitor?.startView(viewController: self, name: "ProductDetail")
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isMovingFromParent {
RUM.monitor?.stopView(viewController: self)
}
}
Сессионный семплинг и GDPR
При включённом RUM нужно получить согласие пользователя до начала записи сессии. В iOS это делается через trackingConsent:
Datadog.set(trackingConsent: userConsentedToAnalytics ? .granted : .notGranted)
Для Sentry аналогично через SentryOptions.enableAutoSessionTracking и SentrySDK.setUser() только после получения consent.
Что делаем
- Выбираем инструмент под стек и бюджет (Firebase / Sentry / Datadog / New Relic)
- Подключаем SDK с правильным
sessionSampleRateпод планируемый трафик - Инструментируем View-переходы (UIKit, SwiftUI, Jetpack Compose, Flutter)
- Настраиваем HTTP-перехватчик для трекинга сетевых ресурсов
- Конфигурируем consent-логику под GDPR
- Строим первичный дашборд: p75/p95 View load time, Error Rate, Long Task Rate
Сроки
Базовая настройка RUM: 1–2 дня. Кастомные атрибуты и дашборды: ещё 1 день. Стоимость рассчитывается индивидуально.







