10 ejemplos para empezar con observabilidad móvil - 7 básicos e 3 intermedios. Cubre fallos nativos, ANRs, errores de JavaScript, y cómo se ajustan a la pila de señales que cada equipo de Expo envía antes del lanzamiento en la tienda.
Crea una aplicación TypeScript en blanco. Los ejemplos utilizan APIs integradas y patrones que funcionan en compilaciones de lanzamiento de Expo SDK 57 - no se requiere SDK de proveedor hasta que conectes Sentry en una página posterior.
Las plataformas móviles clasifican los fallos de manera diferente - tus paneles también deberían.
// src/observability/taxonomy.tsexport type MobileFailureKind = | "native_crash" // proceso terminado - iOS/Android nativo | "js_fatal" // ErrorUtils isFatal - el paquete puede estar en mal estado | "js_non_fatal" // capturado, reportado, la aplicación continúa | "anr" // Android: hilo principal bloqueado ~5s+ (Application Not Responding) | "handled_error"; // API 5xx mostrada en UI - sigue valiendo la pena registrarexport type FailureReport = { kind: MobileFailureKind; message: string; screen?: string; release: string; // compilación nativa: 1.4.2 (42) otaUpdateId?: string; // id de manifiesto de expo-updates sessionId: string;};
Fallo nativo termina la sesión - el usuario debe reiniciar
JS fatal puede o no matar el proceso dependiendo del motor y del sitio del error
ANR es específico de Android - los watchdog de iOS están más cerca de la taxonomía de fallos nativos
Errores manejados pertenecen a los registros y rastreadores de problemas no fatales - no al numerador de la tasa sin fallos
// src/observability/report.tsimport type { FailureReport } from "./taxonomy";type Reporter = (report: FailureReport) => void;export function reportJsError( report: Reporter, error: Error, meta: { isFatal: boolean; screen: string; release: string }) { report({ kind: meta.isFatal ? "js_fatal" : "js_non_fatal", message: error.message, screen: meta.screen, release: meta.release, sessionId: "…", // from getSessionId() });}// Los fallos nativos son capturados por los SDKs nativos de @sentry/react-native / Crashlytics.// La capa de JS solo los ve como "sesión anterior finalizada inesperadamente" en el siguiente lanzamiento.
Instala el SDK de React Native con módulos nativos habilitados - los envoltorios solo de JS pierden SIGABRT
Simboliza tanto mapas de bytecode de Hermes como dSYM nativo / mapeos de ProGuard
Después de un fallo nativo, los registros en el dispositivo se pierden a menos que los hayas enviado en el primer plano anterior - ver Structured Logging On Device
Los JS fatals pueden permitir componentDidCatch en árboles hermanos - los fallos nativos no
Los ANRs provienen de trabajo sincrónico en el hilo de UI - a menudo JSON parse, inundaciones de registro o useMemo pesado en matrices grandes.
import { useEffect, useRef } from "react";import { InteractionManager } from "react-native";export function useMainThreadWatchdog(thresholdMs = 2000) { const lastTick = useRef(Date.now()); useEffect(() => { const id = setInterval(() => { const now = Date.now(); const gap = now - lastTick.current; lastTick.current = now; if (gap > thresholdMs) { console.warn("[perf] event loop gap ms", gap); // reportar no fatal: posible ANR / bloqueo de hilo de JS } }, 500); return () => clearInterval(id); }, [thresholdMs]);}// Difiere trabajo pesado fuera de la ruta críticaexport function deferAfterInteractions(task: () => void) { InteractionManager.runAfterInteractions(task);}
Brechas de 2000ms en un temporizador de 500ms sugieren bloqueo de hilo de JS - investiga antes de que los usuarios vean diálogos de ANR
Los conjuntos de datos grandes de FlatList sin virtualización son una fuente común de ANR - Performance Basics
La decodificación de imágenes en el hilo de JS durante el desplazamiento causa bloqueos - usa activos de tamaño apropiado
Android Vitals reporta ANRs en Play Console - correlaciona con tus etiquetas de versión y OTA