Налаштування моніторингу HTTP-запитів (Response Time, Error Rate) у мобільних застосунках
Response Time та Error Rate—два основні сигнали здоров'я API. Якщо середній час відповіді /api/feed виросте з 200 мс до 1800 мс, користувачі це почувають, але отзивы у App Store з'являться наступного дня. З моніторингом—ви знаєте через 5 хвилин.
Що вимірювати та де зберігати
Два рівні збору метрик:
Клієнтський (in-app): вимірюйте час відповіді з пристрою користувача—включає затримку мережі. Відображає реальний досвід, але шумний: погана мережа одного користувача не означає проблему сервера.
Серверний (APM): інструментуйте сервер, вимірюйте тільки серверний час. Не видить мережевої затримки, але точно показує стан бекенду.
Правильний підхід: обидва рівні. Клієнтський для розуміння UX, серверний для діагностики.
Перехватчик для Axios у React Native
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
type RequestMetric = {
endpoint: string;
method: string;
statusCode: number;
durationMs: number;
timestamp: number;
error?: string;
};
const metricsBuffer: RequestMetric[] = [];
const FLUSH_INTERVAL_MS = 30_000;
const FLUSH_BATCH_SIZE = 50;
function createMonitoredAxios(): AxiosInstance {
const instance = axios.create({ baseURL: API_BASE_URL });
instance.interceptors.request.use((config: AxiosRequestConfig) => {
(config as any).metadata = { startTime: Date.now() };
return config;
});
instance.interceptors.response.use(
(response: AxiosResponse) => {
recordMetric(response.config, response.status, null);
return response;
},
(error) => {
const status = error.response?.status ?? 0;
recordMetric(error.config, status, error.message);
return Promise.reject(error);
}
);
return instance;
}
function recordMetric(config: any, status: number, error: string | null) {
const durationMs = Date.now() - (config?.metadata?.startTime ?? Date.now());
const url = config?.url ?? 'unknown';
const endpoint = new URL(url, API_BASE_URL).pathname; // нормалізуємо без query
metricsBuffer.push({
endpoint,
method: (config?.method ?? 'GET').toUpperCase(),
statusCode: status,
durationMs,
timestamp: Date.now(),
error: error ?? undefined,
});
if (metricsBuffer.length >= FLUSH_BATCH_SIZE) flushMetrics();
}
Нормалізуйте URL у pathname—не хочемо тисячі унікальних метрик /api/users/123, /api/users/456. Потрібен паттерн /api/users/:id.
Агрегація на клієнті: P50/P95/P99
Середнє (mean) час відповіді обманливе: 90% запитів за 100 мс та 10% за 5000 мс дають середнє 590 мс—не відображає реальність. Перцентилі точніші:
function calculatePercentiles(durations: number[]): { p50: number; p95: number; p99: number } {
const sorted = [...durations].sort((a, b) => a - b);
const p = (percentile: number) => sorted[Math.floor(sorted.length * percentile / 100)];
return { p50: p(50), p95: p(95), p99: p(99) };
}
P99—час відповіді для 99% запитів. Якщо P99 зростає при стабільному P50—проблема з повільними запитами для невеликої частини користувачів (конкретний endpoint, конкретна ОС, конкретний регіон).
Відправка метрик: батчинг та пріоритизація
async function flushMetrics() {
if (metricsBuffer.length === 0) return;
const batch = metricsBuffer.splice(0, FLUSH_BATCH_SIZE);
try {
await fetch(`${METRICS_ENDPOINT}/ingest`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ metrics: batch, appVersion: APP_VERSION, platform: Platform.OS }),
});
} catch {
// При помилці відправки—повертаємо у буфер, але не більше MAX_BUFFER_SIZE
metricsBuffer.unshift(...batch.slice(0, MAX_BUFFER_SIZE - metricsBuffer.length));
}
}
Відправляйте метрики через non-critical fetch—помилки відправки не повинні впливати на UX. Буфер обмежено—під час offline не накопичуйте гігабайти.
Готове рішення: Firebase Performance Monitoring
@react-native-firebase/perf робить більшість автоматично: перехоплює fetch/XHR, вимірює час, відправляє у Firebase. Консоль показує дашборд з перцентилями по endpoint.
import perf from '@react-native-firebase/perf';
// Кастомний трейс для критичної операції
const trace = await perf().startTrace('checkout_flow');
trace.putAttribute('userId', userId);
// ... операція ...
await trace.stop();
Для більшості застосунків Firebase Performance—правильний вибір. Для enterprise з вимогами self-hosted—Datadog RUM Mobile або кастомна відправка у InfluxDB/Prometheus.
Алерти по Response Time
Поріг алерту: P95 > 2× baseline за 5-хвилинне вікно. Наприклад, якщо baseline P95 = 400 мс та виросте до 900 мс—алерт у Slack. Error rate > 5% за 10 хвилин—PagerDuty.
Оцінка часу
Firebase Performance Monitoring з кастомними трейсами та базовими алертами: 1 тиждень. Кастомна система метрик з батчингом, перцентилями та Datadog/Grafana-дашбордом: 2–4 тижні.







