| name | sentry-integration |
| description | Sentry error tracking i performance monitoring dla React Native (Expo) + Supabase Edge Functions. Aktywuje się przy pracy z błędami, monitoringiem, captureException, error boundary, śledzeniem błędów, diagnostyką, loggerem, Edge Functions, crash, native crash, awaria, wydajność, raportowanie błędów, exception, wyjątek, React Native, Expo. |
Sentry Integration Guidelines
Kompleksowy przewodnik integracji Sentry error tracking i performance monitoring dla projektu React Native (Expo) + Supabase Edge Functions.
Stan SDK
- React Native SDK:
@sentry/react-native 8.x (Sentry.wrap, expoRouterIntegration, mobileReplayIntegration) ✅
- Edge Functions:
@sentry/deno na Deno 2.x (beforeSend działa; SDK NIE instrumentuje Deno.serve i nie daje scope separation między requestami w tym samym isolate — tak mówi dokumentacja Supabase) ⚠️ — ustaw defaultIntegrations: false, używaj withScope dla izolacji i await flush() przed Response
Table of Contents
Critical Rules
NIGDY NIE ŁAMIESZ TYCH ZASAD:
- ALL ERRORS MUST BE CAPTURED TO SENTRY - w produkcji każdy błąd musi trafić do Sentry
- NIGDY
console.error bez Sentry - w Edge Functions każdy console.error musi mieć captureError()
- MASKUJ DANE OSOBOWE - email musi być maskowany:
user@example.com → us***@example.com
- NIE WYSYŁAJ WRAŻLIWYCH DANYCH - hasła, tokeny, klucze API NIGDY nie trafiają do Sentry
- UŻYWAJ ODPOWIEDNICH POZIOMÓW -
fatal tylko dla krytycznych, error dla operacji
Dobre praktyki (Edge Functions / Supabase)
@sentry/deno działa na Supabase Edge Runtime (Deno 2.x) i wspiera beforeSend, ale
nie instrumentuje Deno.serve — oficjalna dokumentacja Supabase mówi wprost, że SDK nie
zapewnia scope separation między requestami w tym samym isolate. Dlatego izolację kontekstu
trzeba robić ręcznie przez withScope(). Nadal stosuj:
| Zasada | Dlaczego |
|---|
defaultIntegrations: false w Sentry.init() | Bezpieczny default, bo SDK i tak nie instrumentuje Deno.serve ani nie daje scope separation |
Ustawiaj kontekst przez Sentry.withScope() | Izolacja per operacja; unikasz wycieku tagów między requestami |
| Nie ustawiaj globalnych tagów per-request | Globalny scope jest współdzielony w obrębie isolate'u |
await Sentry.flush() przed Response | Isolate może zostać zamrożony zaraz po odpowiedzi |
Maskuj PII w beforeSend | Jeden centralny punkt dla wszystkich zdarzeń |
Zawsze używaj tego wzorca:
Sentry.setTag('user_id', userId);
Sentry.captureException(error);
Sentry.withScope((scope) => {
scope.setTag('user_id', userId);
Sentry.captureException(error);
});
Szczegóły: edge-functions-sentry.md
Error Levels
| Level | Kiedy używać | Przykład |
|---|
fatal | System nie działa, wymaga natychmiastowej interwencji | Brak połączenia z bazą |
error | Operacja nie powiodła się, użytkownik dotknięty | Płatność Stripe nie przeszła |
warning | Problem odwracalny, nie wymaga natychmiastowej akcji | Retry po timeout |
info | Informacje operacyjne | Użytkownik zalogowany |
Quick Reference
Mobile (React Native / Expo)
Inicjalizacja w app/_layout.tsx (Expo Router root, Sentry.wrap):
import * as Sentry from '@sentry/react-native';
import { isRunningInExpoGo } from 'expo';
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
tracesSampleRate: 0.1,
integrations: [
Sentry.expoRouterIntegration({
enableTimeToInitialDisplay: !isRunningInExpoGo(),
}),
],
});
function RootLayout() {
}
export default Sentry.wrap(RootLayout);
Użycie loggera (preferowane):
import { logger } from '@/lib/logger';
import { Alert } from 'react-native';
try {
await riskyOperation();
} catch (error) {
logger.error('Operacja nie powiodła się', error);
Alert.alert('Błąd', 'Wystąpił błąd. Spróbuj ponownie.');
}
Bezpośrednie Sentry (gdy potrzeba więcej kontekstu):
import * as Sentry from '@sentry/react-native';
Sentry.withScope((scope) => {
scope.setTag('operation', 'payment');
scope.setContext('order', { orderId: '123', amount: 100 });
Sentry.captureException(error);
});
Pełny setup (plugin Expo, sourcemaps build+OTA, Session Replay, crash capture natywny vs Expo Go) —
sekcja React Native (Expo) niżej i
react-native-sentry-patterns.md.
Edge Functions (Deno)
Każda funkcja MUSI mieć Sentry z withScope:
import { initSentry, captureError } from '../_shared/sentry.ts';
const Sentry = initSentry('function-name');
Deno.serve(async (req) => {
try {
} catch (error) {
captureError(error, {
operation: 'checkout',
user_id: userId
});
return new Response(JSON.stringify({ error: 'Error' }), { status: 500 });
}
});
Context Enrichment
ZAWSZE dodawaj kontekst do błędów:
Sentry.withScope((scope) => {
scope.setUser({ id: userId, email: maskedEmail });
scope.setTag('service', 'payments');
scope.setTag('endpoint', '/checkout');
scope.setContext('operation', {
type: 'stripe_checkout',
sessionId: session.id,
amount: amount
});
scope.addBreadcrumb({
category: 'payment',
message: 'Starting checkout',
level: 'info'
});
Sentry.captureException(error);
});
Sentry.captureException(error);
GDPR Compliance
Maskowanie emaili - OBOWIĄZKOWE:
beforeSend(event) {
if (event.user?.email) {
event.user.email = event.user.email.replace(/^(.{2}).*(@.*)$/, '$1***$2');
}
return event;
}
export function setSentryUser(user: { id: string; email: string } | null) {
if (user) {
Sentry.setUser({
id: user.id,
email: user.email.replace(/^(.{2}).*(@.*)$/, '$1***$2'),
});
} else {
Sentry.setUser(null);
}
}
Checklist dla Nowego Kodu
Przed każdym PR sprawdź:
Common Mistakes
NIE RÓB:
try {
await operation();
} catch (error) {
}
} catch (error) {
console.error('Error:', error);
}
Sentry.setContext('auth', { token: userToken });
RÓB:
try {
await operation();
} catch (error) {
logger.error('Operacja nie powiodła się', error);
Alert.alert('Błąd', 'Wystąpił błąd. Spróbuj ponownie.');
}
Sentry.setContext('auth', {
userId: user.id,
provider: 'google'
});
React Native (Expo)
Sentry w aplikacji mobilnej ma inny SDK, inny sourcemaps flow i inną integrację z routingiem niż web.
Setup @sentry/react-native (NIE @sentry/react)
bunx expo install @sentry/react-native
W app.json dodaj plugin Sentry żeby sourcemaps były automatycznie uploadowane przy eas build:
{
"expo": {
"plugins": [
[
"@sentry/react-native/expo",
{
"organization": "your-org",
"project": "your-project",
"url": "https://sentry.io/"
}
]
]
}
}
Inicjalizacja w app/_layout.tsx (Expo Router root)
Kanoniczna integracja nawigacji dla Expo Router to Sentry.expoRouterIntegration() — czyta
wewnętrzny navigation ref Expo Router sama, bez ręcznego useNavigationContainerRef +
registerNavigationContainer (to był wzorzec dla reactNavigationIntegration, nieaktualny
dla tego szablonu). Źródło: https://docs.sentry.io/platforms/react-native/tracing/instrumentation/expo-router/
import * as Sentry from '@sentry/react-native';
import { isRunningInExpoGo } from 'expo';
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
enableNative: !isRunningInExpoGo(),
tracesSampleRate: 0.1,
integrations: [
Sentry.expoRouterIntegration({
enableTimeToInitialDisplay: !isRunningInExpoGo(),
}),
],
});
function RootLayout() {
}
export default Sentry.wrap(RootLayout);
enableAutoSessionTracking nie jest tu potrzebne — sesje (release health) są włączone
domyślnie w @sentry/react-native od dawna, jawne ustawienie na true jest redundantne.
Sourcemaps przez EAS Build
Plugin Sentry (skonfigurowany powyżej) automatycznie uploaduje sourcemaps i debug symbole
(dSYM na iOS, ProGuard/NDK mapping na Android) przy każdym eas build na podstawie
SENTRY_AUTH_TOKEN w EAS env:
eas env:create --name SENTRY_AUTH_TOKEN --value "$TOKEN" --visibility secret --environment production
Powtórz z --environment preview jeśli chcesz auto-upload też dla buildów preview.
eas secret:create jest nieaktualne — eas-cli ma dziś tylko rodzinę eas env:*.
Bez tokena: stack traces w Sentry pokażą minified bundle (nieczytelny). Token jest wymagany dla każdego release/preview profilu.
Sourcemaps przy EAS Update (OTA)
Auto-upload z pluginu działa tylko przy natywnym eas build — OTA update (eas update) go nie
wyzwala. Po każdym OTA update wgraj sourcemapy ręcznie:
eas update --branch production
npx sentry-expo-upload-sourcemaps dist
Bez tego kroku crashe zgłoszone po OTA update pokażą zminifikowany stack trace mimo poprawnie
skonfigurowanego pluginu.
Session Replay (Mobile)
Wymaga @sentry/react-native >= 6.5.0. Nagrywa sesje jako sekwencję klatek do diagnozy "co user
widział przed crashem" — dodaj Sentry.mobileReplayIntegration():
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.expoRouterIntegration({ enableTimeToInitialDisplay: !isRunningInExpoGo() }),
Sentry.mobileReplayIntegration(),
],
});
GDPR: maskowanie tekstu, obrazów i webview jest domyślnie włączone (agresywne). Wyłączaj
tylko selektywnie (maskAllText: false itp.) i tylko dla ekranów bez PII — spójnie z maskowaniem
emaili z sekcji GDPR Compliance.
Crash capture — JS errors + native crashes
@sentry/react-native łapie:
- JS errors: automatycznie (przez globalErrorHandler)
- Native crashes (iOS Swift / Android Kotlin): automatycznie pod warunkiem
enableNative: true i build z dev-client / preview / release. Expo Go nie raportuje native crashy (sandbox).
- ANR (Application Not Responding) Android: wbudowane od
@sentry/react-native@5+
- Promise rejections: automatycznie
Navigation breadcrumbs
expoRouterIntegration automatycznie loguje każdą zmianę route jako breadcrumb. W panelu Sentry zobaczysz: Login → Dashboard → Settings → [crash]. Krytyczne dla diagnozy "co user robił przed crashem".
Mobile-specific context
import * as Device from 'expo-device';
import * as Application from 'expo-application';
Sentry.setContext('device', {
model: Device.modelName,
osName: Device.osName,
osVersion: Device.osVersion,
appVersion: Application.nativeApplicationVersion,
buildNumber: Application.nativeBuildVersion,
});
To pomaga filtrować w Sentry per-platform / per-version.
Resources
Szczegółowe wzorce znajdują się w:
- react-native-sentry-patterns.md - Pełna konfiguracja
@sentry/react-native dla tego szablonu: init, Sentry.wrap, expoRouterIntegration, mobileReplayIntegration, error boundary RN, native crashe vs Expo Go, sourcemaps (build + OTA), debug symbole, GDPR
- react-sentry-patterns.md - ⚠️ TYLKO web (React + Vite) — zostaje jako referencja, nie dla tego szablonu mobile
- edge-functions-sentry.md - Wzorce dla Supabase Edge Functions (Deno), shared helpers, Stripe tracking
Skill Status: COMPLETE + sekcja React Native (Expo) zaktualizowana lipiec 2026 (expoRouterIntegration, mobileReplayIntegration, eas env:*, OTA sourcemaps)
Progressive Disclosure: Szczegółowe wzorce w plikach resources/