İçeriğe atla

React Native Expo ile Sentry Entegrasyonu: Pratik Hızlı Rehber

React Native Expo uygulamasına Sentry ekleme rehberi: SDK kurulumu, Expo Router enstrümantasyonu, session replay ve EAS için source map yükleme.

Ayhan Sipahi Ayhan Sipahi

Sentry’nin kurulum wizard’ı bir React Native Expo projesini tek komutla hazırlar; çoğu uygulama için wizard ve bir development build yeterlidir. Saat kaybettiren kısımlar sonrasında başlar: Expo Go native crash’leri ve session replay’i sessizce devre dışı bırakır, EAS Update source map’leri kendiliğinden yüklemez ve app.json içinde unutulan bir auth token uygulamayı kuran her cihaza gider.

Aşağıdaki yapılandırma Expo SDK 50 ve üzeri ile @sentry/react-native paketini varsayar. Eski sentry-expo paketi SDK 50 ile birlikte kullanımdan kaldırıldı; yeni projelerde tercih edilmemeli.

Ön Koşullar#

Başlamadan önce şunlara ihtiyacın var:

  • SDK 50 veya üzeri kullanan bir Expo projesi (SDK 52+ önerilir)
  • Bir Sentry hesabı (ücretsiz plan aylık 5.000 hata sağlar)
  • Sentry panelinde oluşturulmuş bir React Native projesi
  • Sentry’den üç tanımlayıcı: Organization slug, Project name ve DSN
  • Sentry ayarlarından üretilmiş bir Organization Auth Token

Adım 1: Kurulum#

Sentry wizard kurulumun büyük kısmını otomatize eder. Proje kök dizininden çalıştır:

npx @sentry/wizard@latest -i reactNative

Wizard Metro config, Expo plugin config ve temel SDK başlatmasını halleder. Manuel kurulumu tercih ediyorsan veya wizard senin ortamında çalışmıyorsa, paketi doğrudan kur:

npx expo install @sentry/react-native

Manuel kurulum üç dosyayı kendin yapılandırmanı gerektirir: Metro config, Expo plugin kaydı ve root layout içindeki SDK başlatması.

Adım 2: Metro Yapılandırması#

Sentry’nin source map üretimi için Metro bundler’a bağlanması gerekiyor. metro.config.js dosyanı şu şekilde güncelle:

// metro.config.js
const { getSentryExpoConfig } = require("@sentry/react-native/metro");

const config = getSentryExpoConfig(__dirname);

module.exports = config;

Zaten özel bir Metro config’in varsa, tamamen değiştirmek yerine mevcut config’ini getSentryExpoConfig ile sar.

Adım 3: Expo Plugin Yapılandırması#

Sentry plugin’ini app.json (veya app.config.js) dosyana ekle:

{
  "expo": {
    "plugins": [
      [
        "@sentry/react-native/expo",
        {
          "url": "https://sentry.io/",
          "project": "my-expo-app",
          "organization": "my-org"
        }
      ]
    ]
  }
}

Warning

authToken değerini asla app.json veya app.config.js içine koyma. Bu yapılandırma dosyası uygulama paketine gömülür ve çalışma zamanında erişilebilir olur. Auth token’ı environment variable veya EAS secret olarak ayarla. Bu, Expo SDK 50 migration dokümantasyonunda belgelenmiş bir güvenlik sorunuydu.

Adım 4: Expo Router ile SDK Başlatma#

Ana başlatma root layout dosyasında yapılır. Bu örnek, Expo Router navigasyon takibi ile performans izleme, ortam yapılandırması ve session replay içerir:

// app/_layout.tsx
import { Stack, useNavigationContainerRef } from "expo-router";
import * as Sentry from "@sentry/react-native";
import { isRunningInExpoGo } from "expo";
import React from "react";

const navigationIntegration = Sentry.reactNavigationIntegration({
  enableTimeToInitialDisplay: !isRunningInExpoGo(),
});

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",

  // Ortam yapılandırması
  environment: __DEV__ ? "development" : "production",

  // Performans izleme
  tracesSampleRate: __DEV__ ? 1.0 : 0.2,
  enableNativeFramesTracking: !isRunningInExpoGo(),

  // Session replay
  replaysOnErrorSampleRate: 1.0,
  replaysSessionSampleRate: __DEV__ ? 1.0 : 0.1,

  // Entegrasyonlar
  integrations: [
    navigationIntegration,
    Sentry.mobileReplayIntegration(),
  ],
});

function RootLayout() {
  const ref = useNavigationContainerRef();

  React.useEffect(() => {
    if (ref?.current) {
      navigationIntegration.registerNavigationContainer(ref);
    }
  }, [ref]);

  return <Stack />;
}

export default Sentry.wrap(RootLayout);

Bu yapılandırmada dikkat edilmesi gereken birkaç nokta:

  • Production’da tracesSampleRate: 0.2 işlemlerin %20’sini yakalar. Bunu production’da 1.0 olarak ayarlamak kotanı hızla tüketir ve uygulama performansını etkileyebilir.
  • replaysOnErrorSampleRate: 1.0 her hata için session replay yakalar; en değerli kullanım senaryosu budur. 0.1 oranındaki genel session replay’ler aşırı veri olmadan bir örneklem sağlar.
  • isRunningInExpoGo() korumaları, Expo Go’da sessizce başarısız olacak veya çökecek native-only özelliklerin etkinleştirilmesini engeller.

Adım 5: Expo Go ve Development Build Farkları#

Bu, en yaygın kafa karışıklığı kaynaklarından biri. Expo Go, Sentry’nin native modüllerini içermez, bu da işlevselliği önemli ölçüde kısıtlar.

Development Build / EAS Build

JS Hata Yakalama - Çalışıyor

Mesaj Yakalama - Çalışıyor

Breadcrumbs - Çalışıyor

Kullanıcı Context - Çalışıyor

Native Crash - Çalışıyor

Frame Takibi - Çalışıyor

Session Replay - Çalışıyor

Native Profiling - Çalışıyor

Expo Go

JS Hata Yakalama - Çalışıyor

Mesaj Yakalama - Çalışıyor

Breadcrumbs - Çalışıyor

Kullanıcı Context - Çalışıyor

Native Crash - Kullanılamıyor

Frame Takibi - Kullanılamıyor

Session Replay - Kullanılamıyor

Native Profiling - Kullanılamıyor

isRunningInExpoGo() koruması, Expo Go’da çalışırken native-only özelliklerin etkinleştirilmesini engeller:

Sentry.init({
  // ...
  enableNativeFramesTracking: !isRunningInExpoGo(),
  profilesSampleRate: isRunningInExpoGo() ? 0 : 1.0,
});

Tam Sentry işlevselliği için, göndermeden önce mutlaka development build veya EAS Build ile doğrula.

Adım 6: Error Boundary’ler#

Sentry, React render hatalarını yakalayan ve otomatik olarak raporlayan bir ErrorBoundary bileşeni sağlar:

import * as Sentry from "@sentry/react-native";
import { View, Text, TouchableOpacity } from "react-native";

function ErrorFallback({
  error,
  resetError,
}: {
  error: Error;
  resetError: () => void;
}) {
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text style={{ fontSize: 18, fontWeight: "bold" }}>
        Bir şeyler ters gitti
      </Text>
      <Text style={{ color: "#666", marginTop: 8 }}>
        {error.message}
      </Text>
      <TouchableOpacity
        onPress={resetError}
        style={{
          marginTop: 16,
          padding: 12,
          backgroundColor: "#362d59",
          borderRadius: 8,
        }}
      >
        <Text style={{ color: "#fff" }}>Tekrar Dene</Text>
      </TouchableOpacity>
    </View>
  );
}

export function ScreenWithErrorBoundary() {
  return (
    <Sentry.ErrorBoundary
      fallback={({ error, resetError }) => (
        <ErrorFallback error={error} resetError={resetError} />
      )}
      beforeCapture={(scope) => {
        scope.setTag("component", "MainScreen");
      }}
    >
      <MainScreenContent />
    </Sentry.ErrorBoundary>
  );
}

beforeCapture callback’i context tag’leri eklemeyi sağlar, bu da hataları Sentry panelinde filtrelemeyi ve gruplamayı kolaylaştırır.

Note

Geliştirme modunda React, error boundary’lerin yakaladığı hataları global error handler’a yeniden fırlatır; bu da tekrarlayan raporlara yol açabilir. Error boundary davranışını production build’lerde test et.

Adım 7: EAS Build ve EAS Update için Source Map’ler#

Production’da okunabilir stack trace’ler almak için düzgün yüklenmiş source map’ler gerekir. Süreç EAS Build ve EAS Update arasında farklılık gösterir.

EAS Build

EAS Update

Kod Değişikliği

Dağıtım Yöntemi

Native Build

Otomatik Source Map Yükleme

Sentry Release Oluşturuldu

OTA Bundle

npx expo export

npx sentry-expo-upload-sourcemaps dist

Source Map Yüklendi

Panelde Sembolik Stack Trace

EAS Build (Otomatik)#

Native build’ler için source map yükleme otomatiktir. Sadece auth token’ı EAS secret olarak ayarla:

eas env:create --name SENTRY_AUTH_TOKEN --value "sntrys_YOUR_TOKEN_HERE" --scope project --visibility secret --environment production

Bu kadar. Sentry Expo plugin’i build sürecinde geri kalan her şeyi halleder.

EAS Update (Manuel)#

OTA güncellemeleri source map’leri otomatik olarak yüklemez. Her eas update sonrası manuel olarak yüklemen gerekir:

npx expo export --platform all
npx sentry-expo-upload-sourcemaps dist

Okunamayan stack trace’lerle güncelleme göndermekten kaçınmak için bunu CI/CD pipeline’ında otomatize et.

Adım 8: EAS Update Metadata Etiketleme#

OTA güncellemeleri kullanırken, Sentry olaylarını güncelleme metadata’sı ile etiketlemek hataları güncelleme sürümüne göre filtrelemeyi mümkün kılar:

import * as Sentry from "@sentry/react-native";
import * as Updates from "expo-updates";

function tagSentryWithUpdateInfo() {
  const manifest = Updates.manifest;
  const metadata =
    manifest && "metadata" in manifest ? manifest.metadata : undefined;
  const updateGroup =
    metadata && typeof metadata === "object" && "updateGroup" in metadata
      ? (metadata as { updateGroup: string }).updateGroup
      : undefined;

  const scope = Sentry.getGlobalScope();

  scope.setTag("expo-update-id", Updates.updateId ?? "embedded");
  scope.setTag("expo-is-embedded-update", String(Updates.isEmbeddedLaunch));

  if (updateGroup) {
    scope.setTag("expo-update-group-id", updateGroup);
  }
}

// Sentry.init() sonrası, uygulama yaşam döngüsünde erken çağır
tagSentryWithUpdateInfo();

Bu özellikle bir OTA güncellemesi regresyon getirdiğinde kullanışlıdır: hata artışına hangi güncelleme grubunun neden olduğunu hemen tespit edebilirsin.

Adım 9: Entegrasyonu Doğrulama#

Production’a geçmeden önce, basit bir test bileşeni ile hataların Sentry panelinde doğru görünüp görünmediğini kontrol et:

import * as Sentry from "@sentry/react-native";
import { Button, View } from "react-native";

export function SentryTestButtons() {
  return (
    <View style={{ gap: 12, padding: 16 }}>
      <Button
        title="JS Hatası Test Et"
        onPress={() => {
          Sentry.captureException(new Error("Test JS error from Expo"));
        }}
      />

      <Button
        title="Yakalanmamış Hata Test Et"
        onPress={() => {
          throw new Error("Unhandled test error");
        }}
      />

      <Button
        title="Native Crash Test Et"
        onPress={() => {
          Sentry.nativeCrash();
        }}
      />
    </View>
  );
}

Her hatayı tetikledikten sonra Sentry panelini kontrol et. Stack trace’lerin düzgün sembolik hale getirildiğinden emin ol: minified kod yerine orijinal kaynak dosya adlarını ve satır numaralarını görmelisin.

Tip

Native crash testi sadece development build’lerde çalışır, Expo Go’da çalışmaz. Butona basınca hiçbir şey olmuyorsa, muhtemelen Expo Go’da çalışıyorsundur.

Sorun Giderme#

Source Map’ler Minified Kod Gösteriyor#

Neden: Source map’ler yüklenmemiş veya release/dist değerleri uygulama ile yüklenen map’ler arasında eşleşmiyor.

Çözüm: Otomatik release adlandırma kullan (varsayılan). Sentry.init() içinde özel release veya dist değerleri ayarlarsan, otomatik yükleme betiği bunları tespit edemez. Ya varsayılanlarla kal ya da eşleşen release/dist değerleriyle source map’leri manuel olarak yükle.

Neden: registerNavigationContainer navigasyon ref ile hiç çağrılmamış.

Çözüm: useNavigationContainerRef() fonksiyonunun Sentry’nin başlatıldığı aynı bileşende çağrıldığından ve ref’in bir useEffect içinde kaydedildiğinden emin ol.

Geliştirme Ortamında Tekrarlayan Hata Raporları#

Neden: React’in geliştirme modu, error boundary’ler tarafından yakalanan hataları global handler’a yeniden fırlatır.

Çözüm: Error boundary davranışını production build’lerde test et. Gürültü rahatsız ediyorsa enabled: !__DEV__ ile Sentry’yi geliştirme ortamında devre dışı bırakabilirsin.

sentry-expo Paketi Hataları#

Neden: sentry-expo paketi Expo SDK 50 ile birlikte kullanımdan kaldırılmıştır ve artık bakımı yapılmamaktadır.

Çözüm: Doğrudan @sentry/react-native paketine geç. Sentry, dokümantasyonunda bir geçiş rehberi sağlıyor.

Yüksek Olay Hacmi Kotayı Tüketiyor#

Neden: Production için örnekleme oranları çok yüksek ayarlanmış.

Çözüm: Düşük oranlar kullan: tracesSampleRate: 0.1-0.2, replaysSessionSampleRate: 0.1. Hata replay’leri en değerli olduğu için replaysOnErrorSampleRate: 1.0 tut.

Sürüm Uyumluluğu#

BileşenMinimum SürümÖnerilen
@sentry/react-native7.x8.x (güncel)
Expo SDK5052+
React Native0.73+0.76+
iOS Deployment Target15.0 (v8 için)15.0+
Android Gradle Plugin7.4.0 (v8 için)8.x

Note

Sürüm 8, native SDK’ları (Cocoa v9, CLI v3, Android Gradle Plugin v6) minimum sürüm gereksinimlerinde köklü değişikliklerle günceller. Yükseltmeden önce release notlarını kontrol et.

Varsayılanlar ve İstisnalar#

Çoğu Expo uygulaması için wizard ve bir development build yeterli. npx @sentry/wizard@latest -i reactNative Metro ve plugin yapılandırmasını yazar; development build ise Expo Go’nun sağlayamadığı native crash raporlamasını, frame takibini ve session replay’i açar. SENTRY_AUTH_TOKEN değerini app.json yerine EAS secret’larında tut ve production örneklemesine düşük başla: trace’ler için %10-20, session replay’ler için %10, hata replay’leri için %100. Bu oranların değişmesi gerekip gerekmediğini kota verisi kısa sürede gösterir.

İki durum varsayılanların ötesinde iş gerektirir. OTA güncellemesi yayınlıyorsan, sentry-expo-upload-sourcemaps her eas update sonrası CI’da çalışmalı; çünkü EAS Update source map’leri kendiliğinden yüklemez. Sık yayınlıyorsan, bir regresyonun hangi güncelleme grubundan geldiğini izleyebilmek için olayları expo-updates metadata’sı ile etiketle.

Kaynaklar#

İlgili yazılar