Sentry para React Native
@sentry/react-native no Expo SDK 57 - inicialização, source maps, release health e breadcrumbs configurados para builds EAS. Este cookbook assume que você já entende a pilha de sinais de Fundamentos de Observabilidade.
Busque em todas as páginas da documentação
@sentry/react-native no Expo SDK 57 - inicialização, source maps, release health e breadcrumbs configurados para builds EAS. Este cookbook assume que você já entende a pilha de sinais de Fundamentos de Observabilidade.
npx expo install @sentry/react-native
npx @sentry/wizard@latest -i reactNativeO assistente adiciona configuração de plugin Metro, hooks nativos e etapas de build EAS. Para configuração manual, fixe versões compatíveis com RN 0.86:
{
"dependencies": {
"@sentry/react-native": "^6.0.0",
"expo": "~57.0.4",
"react": "19.2.3",
"react-native": "0.86.0"
}
}Ferramentas: Estes exemplos visam Expo SDK 57 (
expo~57.0.4), React Native 0.86.0 e React 19.2.3.
Cartão de receita de referência rápida - pronto para copiar e colar.
1. Inicialize no ponto de entrada mais cedo
// app/_layout.tsx - deve ser executado antes de outros efeitos colaterais de importação
import * as Sentry from "@sentry/react-native";
import { Stack } from "expo-router";
import * as Application from "expo-application";
import * as Updates from "expo-updates";
const nativeVersion = Application.nativeApplicationVersion ?? "0.0.0";
const buildNumber = Application.nativeBuildVersion ?? "0";
const release = `${nativeVersion}+${buildNumber}`;
const dist = Updates.updateId ?? buildNumber;
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
environment: process.env.EXPO_PUBLIC_APP_ENV ?? "development",
release,
dist,
enableAutoSessionTracking: true,
tracesSampleRate: 0.2,
attachStacktrace: true,
beforeSend(event) {
// Remova PII - nunca envie emails ou tokens brutos
if (event.user?.email) delete event.user.email;
return event;
},
});
function RootLayout() {
return <Stack />;
}
export default Sentry.wrap(RootLayout);2. EAS build - faça upload de source maps
// Trecho do eas.json
{
"build": {
"production": {
"env": {
"SENTRY_AUTH_TOKEN": "@sentry-auth-token",
"SENTRY_ORG": "your-org",
"SENTRY_PROJECT": "your-rn-app"
}
}
}
}# Após a conclusão do EAS Build, os hooks sentry-expo / wizard fazem o upload:
# - Source maps do Hermes (JS)
# - Símbolos de depuração para frames nativos (dSYM do iOS, NDK do Android se usado)
eas build --platform all --profile production3. Wrapper de breadcrumbs de navegação (Expo Router)
import { useEffect } from "react";
import { usePathname } from "expo-router";
import * as Sentry from "@sentry/react-native";
export function useSentryRouteBreadcrumb() {
const pathname = usePathname();
useEffect(() => {
Sentry.addBreadcrumb({
category: "navigation",
message: pathname,
level: "info",
});
Sentry.setTag("route", pathname);
}, [pathname]);
}4. Wrapper de breadcrumb de rede
export async function sentryFetch(input: RequestInfo, init?: RequestInit) {
const start = Date.now();
const url = typeof input === "string" ? input : input.url;
try {
const res = await fetch(input, init);
Sentry.addBreadcrumb({
category: "http",
message: `${init?.method ?? "GET"} ${url}`,
data: { status: res.status, durationMs: Date.now() - start },
level: res.ok ? "info" : "warning",
});
return res;
} catch (err) {
Sentry.addBreadcrumb({
category: "http",
message: `${init?.method ?? "GET"} ${url} failed`,
data: { durationMs: Date.now() - start },
level: "error",
});
throw err;
}
}Quando usar isso:
Bootstrap completo com contexto de sessão, escopo de usuário ciente de autenticação e integração de boundary de erro.
// src/observability/sentry.ts
import * as Sentry from "@sentry/react-native";
import * as Application from "expo-application";
import * as Updates from "expo-updates";
export function initSentry() {
const version = Application.nativeApplicationVersion ?? "0.0.0";
const build = Application.nativeBuildVersion ?? "0";
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
environment: process.env.EXPO_PUBLIC_APP_ENV,
release: `${version}+${build}`,
dist: Updates.updateId ?? build,
enableAutoSessionTracking: true,
enableNative: true,
enableNativeCrashHandling: true,
tracesSampleRate: __DEV__ ? 1.0 : 0.15,
integrations: [
Sentry.reactNativeTracingIntegration(),
],
});
}
export function setSentryUser(userId: string | null) {
if (userId) {
Sentry.setUser({ id: userId });
} else {
Sentry.setUser(null);
}
}
export function captureWithContext(error: unknown, context?: Record<string, unknown>) {
Sentry.withScope((scope) => {
if (context) scope.setContext("extra", context);
Sentry.captureException(error);
});
}// app/_layout.tsx
import { useEffect } from "react";
import { Stack } from "expo-router";
import * as Sentry from "@sentry/react-native";
import { initSentry, setSentryUser } from "@/observability/sentry";
import { useSentryRouteBreadcrumb } from "@/observability/useSentryRouteBreadcrumb";
import { useAuth } from "@/features/auth/useAuth";
initSentry();
function RootLayout() {
const { userId } = useAuth();
useSentryRouteBreadcrumb();
useEffect(() => {
setSentryUser(userId);
}, [userId]);
return (
<Sentry.ErrorBoundary fallback={<CrashFallback />}>
<Stack />
</Sentry.ErrorBoundary>
);
}
function CrashFallback() {
return null; // sua UI de recuperação
}
export default Sentry.wrap(RootLayout);// Emparelhe com o logout de autenticação - limpe o escopo do usuário
// setSentryUser(null) no logout - veja ../auth-session/mobile-auth-basics/O Hermes envia bytecode em builds de produção. Sem mapas enviados, o Sentry mostra index.android.bundle:1:234567.
| Artefato | Quando | Propósito |
|---|---|---|
Hermes .map | Todo build de produção EAS | Pilha JS → linhas .tsx |
| iOS dSYM | Build nativo iOS | Frame nativo → Swift/ObjC |
| Mapeamento ProGuard | Release Android | Java ofuscado → símbolos |
# Verifique se a release existe no Sentry antes de enviar OTA
sentry-cli releases list | grep "1.4.2+42"release em Sentry.init deve corresponder exatamente à string da release enviada pela CLIdist diferencia bundles OTA que compartilham a mesma release nativa - use Updates.updateIdRelacionado: Fundamentos de Atualizações OTA - quando alterações de JS são enviadas sem revisão da loja
O Release Health do Sentry rastreia sessões e taxas de "crash-free" por release + environment.
// Sessões iniciam automaticamente com enableAutoSessionTracking: true
// Terminam em crash, ou em background além de sessionTrackingIntervalMillis (padrão 30s)
Sentry.init({
// ...
enableAutoSessionTracking: true,
sessionTrackingIntervalMillis: 30000,
});production vs previewdistenvironment| Categoria | Fonte | Exemplo |
|---|---|---|
navigation | Caminho do Expo Router | /checkout/payment |
http | fetch encapsulado | POST /v1/orders 201 |
auth | Manipuladores de login/logout | refresh_token_rotated |
ui | Ações primárias do usuário | tap_place_order |
console | Sentry.captureConsoleIntegration | apenas avisos de desenvolvimento |
Sentry.addBreadcrumb({
category: "auth",
message: "token_refresh_failed",
level: "warning",
data: { reason: "invalid_grant" }, // sem tokens brutos
});O tracing do Sentry se integra com navegação e fetch - expandido em Monitoramento de Performance.
Sentry.startSpan({ name: "load_feed", op: "ui.load" }, async () => {
await fetchFeed();
});eas build --profile development antes da produção.app/_layout.tsx como um efeito colateral, ou em um instrumentation.ts dedicado importado primeiro.Sentry.wrap no componente raiz uma vez.captureException e re-lance de boundaries a menos que seja intencional.ErrorUtils - veja Manipuladores Globais de Erro.1.4.2+42).Versões da Pilha: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026