Hata Yönetimi ve Logging
Error Boundary'ler, global error handler'lar, hata sayfaları ve production error tracking stratejisi.
Achidemy, kapsamlı bir hata yönetimi sistemi kullanır. React Error Boundary’ler, global error handler’lar ve özel hata sayfaları ile kullanıcı deneyimi korunur ve hatalar loglanır.
Error Boundary Bileşenleri
Section titled “Error Boundary Bileşenleri”1. ReactErrorBoundary (Global)
Section titled “1. ReactErrorBoundary (Global)”Dosya: app/components/ErrorBoundary.tsx; onError callback ve Sentry çağrıları app/root.tsx içinde tanımlı (import * as Sentry from "@sentry/react").
Kullanım: Uygulama kökünde (app/root.tsx) tüm route’ları sarmalar.
<ReactErrorBoundary onError={(error: Error, errorInfo: React.ErrorInfo) => { if (import.meta.env.PROD) { Sentry.captureException(error, { contexts: { react: errorInfo } }); } }}> <Outlet /></ReactErrorBoundary>Özellikler:
- Component hatalarını yakalar
- Fallback UI gösterir
- Hata bilgilerini loglar
- Production’da Sentry’ye gönderilir (bkz. Monitoring ve Observability)
2. Route ErrorBoundary
Section titled “2. Route ErrorBoundary”Dosya: app/root.tsx — ErrorBoundary() export fonksiyonu
Kullanım: React Router route hatalarını yakalar (loader/action hataları).
export function ErrorBoundary() { const error = useRouteError(); const location = useLocation();
useEffect(() => { console.error("Route ErrorBoundary caught an error:", error); if (import.meta.env.PROD) { Sentry.captureException(error, { tags: { route: location.pathname } }); } }, [error, location.pathname]);
const status = isRouteErrorResponse(error) ? error.status : 500;
// Status koduna göre uygun hata sayfasını seç const getErrorPage = () => { switch (status) { case 401: return UnauthorizedPage; case 404: return NotFoundPage; default: return ServerErrorPage; } };
const ErrorPage = getErrorPage(); return <ErrorPage />;}Hata Türleri:
- 401:
UnauthorizedPagegösterilir (oturum sonlandırıldı) - 404:
NotFoundPagegösterilir - 500:
ServerErrorPagegösterilir
3. ErrorFallback Component
Section titled “3. ErrorFallback Component”Dosya: app/components/ErrorBoundary.tsx
Özellikler:
- Kullanıcı dostu hata mesajı
- Geliştirme modunda hata detayları gösterilir
- “Sayfayı Yenile” ve “Ana Sayfaya Dön” butonları
- Dil desteği (path’den dil çıkarılır)
Global Error Handlers
Section titled “Global Error Handlers”Dosya: app/root.tsx — Layout component’i içinde
Unhandled Promise Rejection
Section titled “Unhandled Promise Rejection”useEffect(() => { const handleUnhandledRejection = (event: PromiseRejectionEvent) => { console.error("Unhandled Promise Rejection:", event.reason); if (import.meta.env.PROD) { Sentry.captureException(event.reason, { tags: { type: "unhandled_rejection" } }); } };
window.addEventListener("unhandledrejection", handleUnhandledRejection); return () => { window.removeEventListener("unhandledrejection", handleUnhandledRejection); };}, []);Global Error Event
Section titled “Global Error Event”useEffect(() => { const handleError = (event: ErrorEvent) => { console.error("Global Error:", event.error); if (import.meta.env.PROD) { Sentry.captureException(event.error, { tags: { type: "global_error" } }); } };
window.addEventListener("error", handleError); return () => { window.removeEventListener("error", handleError); };}, []);Hata Sayfaları
Section titled “Hata Sayfaları”Tüm hata sayfaları tam ekran tasarıma sahiptir ve Navbar/Footer gösterilmez.
401 Unauthorized
Section titled “401 Unauthorized”Dosya: app/routes/401.tsx
Özellikler:
- “Oturum sonlandırıldı” mesajı
- Amber/sarı renk teması (güvenlik uyarısı)
ShieldAlertikonu ile güvenlik vurgusu- “Tekrar giriş yap” ve “Ana sayfaya dön” butonları
- Güvenlik uyarı kutusu (şifre değiştirme önerisi)
- Çoklu dil desteği (tr/en/es/de/fr/ja)
Kullanım Senaryoları:
- Hesap paylaşımı nedeniyle oturum düşürüldüğünde
- Session süresi dolduğunda
- Yetkisiz erişim denemelerinde
404 Not Found
Section titled “404 Not Found”Dosya: app/routes/404.tsx
Özellikler:
- Kullanıcı dostu “Sayfa Bulunamadı” mesajı
- Mavi renk teması
- Ana sayfaya dönüş linki
- Dil desteği
500 Server Error
Section titled “500 Server Error”Dosya: app/routes/500.tsx
Özellikler:
- “Sunucu Hatası” mesajı
- Kırmızı/rose renk teması
- Geliştirme modunda hata detayları
- Ana sayfaya dönüş linki
Navbar/Footer Gizleme
Section titled “Navbar/Footer Gizleme”Dosya: app/root.tsx
Hata sayfalarında Navbar ve Footer gizlenir:
const isErrorRoute = matches.some((m) => [ "error-401", "error-404", "error-500", "lang-401", "lang-404", "lang-500", "lang-catchall-404", "catchall-404", ].includes(m.id));
// Navbar ve Footer gizlenir{!isErrorRoute && <Navbar />}{!isErrorRoute && <Footer />}API Route Hata Yönetimi
Section titled “API Route Hata Yönetimi”Loader/Action Hataları
Section titled “Loader/Action Hataları”Örnek: app/routes/api.stripe.webhook.ts
export async function action({ request, context }: ActionFunctionArgs) { try { // Webhook işleme } catch (error) { console.error("Stripe webhook error:", error);
// Hata yanıtı return json( { error: "Webhook processing failed" }, { status: 500 } ); }}GraphQL Hataları
Section titled “GraphQL Hataları”Dosya: app/graphql/schema.ts
const schema = createSchema({ typeDefs, resolvers: { Query: { // ... }, Mutation: { submitExercise: async (_, { exerciseId, code }, { db, user }) => { try { // Mutation logic } catch (error) { console.error("GraphQL mutation error:", error); throw new GraphQLError("Mutation failed", { extensions: { code: "INTERNAL_SERVER_ERROR" } }); } } } }});Logging Stratejisi
Section titled “Logging Stratejisi”Development
Section titled “Development”- Console Logging:
console.error,console.warn,console.log - Hata Detayları: Tam stack trace ve hata bilgileri gösterilir
Production
Section titled “Production”- Error Tracking: Sentry aktif; Worker, client ve Stripe webhook hataları Sentry’ye gönderilir. Detay için Monitoring ve Observability sayfasına bakın.
- Structured Logging: Cloudflare Workers Logs kullanılır
- Hassas Bilgi: Kullanıcı bilgileri ve API key’ler loglanmaz
Cloudflare Workers Logs
Section titled “Cloudflare Workers Logs”Yapılandırma: wrangler.toml
[observability.logs]enabled = truehead_sampling_rate = 1persist = trueinvocation_logs = trueKullanım:
console.error("Error occurred:", error);console.log("Request details:", { path: url.pathname, method: request.method });Best Practices
Section titled “Best Practices”1. Hata Mesajları
Section titled “1. Hata Mesajları”- Kullanıcıya: Genel, anlaşılır mesajlar
- Geliştiriciye: Detaylı hata bilgileri (sadece development modunda)
2. Hata Türleri
Section titled “2. Hata Türleri”| Hata Türü | HTTP Status | Aksiyon |
|---|---|---|
| Validation Error | 400 | Kullanıcıya form hatası göster |
| Authentication Error | 401 | Login sayfasına yönlendir |
| Authorization Error | 403 | Erişim reddedildi mesajı |
| Not Found | 404 | 404 sayfası göster |
| Server Error | 500 | 500 sayfası göster |
3. Try-Catch Kullanımı
Section titled “3. Try-Catch Kullanımı”// ✅ İyi: Spesifik hata yakalamatry { await processPayment();} catch (error) { if (error instanceof StripeError) { // Stripe hatası } else { // Genel hata }}
// ❌ Kötü: Genel catchtry { await processPayment();} catch (error) { // Tüm hatalar aynı şekilde işleniyor}4. React #300 (Rendered fewer hooks)
Section titled “4. React #300 (Rendered fewer hooks)”React, aynı bileşende her render’da aynı sayıda ve sırada hook çağrılmasını zorunlu kılar. Sayfa geçişlerinde (örn. course → bundle) veya loading sırasında hook’lardan önce return <Skeleton /> veya return null yapılırsa, bazı render’larda daha az hook çalışır ve “Minified React error #300” (Rendered fewer hooks than expected) oluşur.
Önlem: Route bileşenlerinde:
useLoaderDatave diğer tüm hook’lar erken return’lerden önce çağrılır.- Loading veya veri yokluğuna göre skeleton / null return’ü yalnızca tüm hook’lar bittikten sonra yapılır.
- Loader verisi
loaderData?.fieldve?? []ile güvenli kullanılır; hesaplamalar (reduce vb.) hook’lardan sonra ve atma riski olmayacak şekilde yazılır.
Bkz. Kod Konvansiyonları — Route bileşeninde hook sırası ve skeleton.
5. Error Tracking (Sentry)
Section titled “5. Error Tracking (Sentry)”Sentry entegrasyonu aktif; hatalar app/root.tsx ve workers/app.ts içinde Sentry.captureException ile gönderilir. Stripe webhook’ta imza, sepet satışı ve refund bloklarında özel tag/extra ile raporlanır. Çalışma yapısı ve tag listesi için Monitoring ve Observability — Sentry bölümüne bakın.
İlgili Dosyalar
Section titled “İlgili Dosyalar”app/components/ErrorBoundary.tsx— React Error Boundary bileşeniapp/root.tsx— Global error handler’lar, Sentry.captureException ve Route ErrorBoundaryapp/entry.client.tsx— Sentry.init (client)app/routes/401.tsx— 401 Unauthorized sayfasıapp/routes/404.tsx— 404 Not Found sayfasıapp/routes/500.tsx— 500 Server Error sayfasıapp/routes/api.stripe.webhook.ts— Stripe webhook Sentry sensörleriwrangler.toml— Observability ve Sentry DSN değişkenleri
İlgili Sayfalar
Section titled “İlgili Sayfalar”- Monitoring ve Observability — Sentry çalışma yapısı, tag’ler ve ortam değişkenleri
- Hesap Güvenliği ve Oturum Yönetimi — Hesap paylaşımı engelleme, 401 sayfası detayları