Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Logowanie i monitoring błędów

Na statku kosmicznym każda awaria jest rejestrowana w czarnej skrzynce. Bez niej zaloga nie mogłaby analizowac przyczyn problemów po fakcie. W aplikacjach React mamy dokladnie ten sam problem -- jeśli błąd wystapi u uzytkownika na produkcji, a my go nie zalogujemy, nigdy sie o nim nie dowiemy. Logowanie i monitoring błędów to Twoja czarna skrzynka produkcyjna.

Strategie logowania błędów

W srodowisku produkcyjnym potrzebujemy kilku warstw logowania:

1. console.error -- tylko do developmentu

console.error
jest przydatny podczas pracy lokalnej, ale na produkcji uzytkownik go nie widzi, a Ty nie masz do niego dostepu.

1// Dobre do developmentu, bezuzyteczne na produkcji
2componentDidCatch(error, errorInfo) {
3  console.error('Error caught:', error);
4  console.error('Component stack:', errorInfo.componentStack);
5}

2. Logowanie do zewnetrznego serwisu

Na produkcji błędy musza byc wysylane do serwisu monitorujacego:

1class ErrorBoundary extends React.Component {
2  componentDidCatch(error, errorInfo) {
3    // Wyslanie do serwisu monitorujacego
4    logErrorToService({
5      message: error.message,
6      stack: error.stack,
7      componentStack: errorInfo.componentStack,
8      timestamp: new Date().toISOString(),
9      url: window.location.href,
10      userAgent: navigator.userAgent,
11    });
12  }
13
14  // ...render z fallback
15}
16
17async function logErrorToService(errorData) {
18  try {
19    await fetch('/api/errors', {
20      method: 'POST',
21      headers: { 'Content-Type': 'application/json' },
22      body: JSON.stringify(errorData),
23    });
24  } catch (e) {
25    // Fallback -- nie blokuj aplikacji jesli logowanie sie nie powiedzie
26    console.error('Failed to log error:', e);
27  }
28}

Sentry i serwisy error tracking

Sentry to najpopularniejszy serwis do monitorowania błędów w aplikacjach JavaScript i React. Inne popularne narzedzia to LogRocket, Bugsnag, Datadog i New Relic.

Podstawowa integracja z Sentry

1import * as Sentry from '@sentry/react';
2
3// Inicjalizacja w main/index.js
4Sentry.init({
5  dsn: 'https://klucz@sentry.io/projekt',
6  environment: 'production',
7  // Procent sesji do rejestrowania (performance)
8  tracesSampleRate: 0.2,
9});
10
11// Sentry automatycznie przechwytuje:
12// - Nieobsluzone wyjatki (uncaught exceptions)
13// - Nieobsluzone rejection Promise
14// - Bledy sieciowe

Sentry z Error Boundary

1import * as Sentry from '@sentry/react';
2
3// Sentry dostarcza gotowy Error Boundary
4function App() {
5  return (
6    <Sentry.ErrorBoundary
7      fallback={({ error }) => (
8        <div className="error-page">
9          <h2>Cos poszlo nie tak</h2>
10          <p>Blad zostal automatycznie zgłoszony</p>
11          <button onClick={() => window.location.reload()}>
12            Odswierz strone
13          </button>
14        </div>
15      )}
16    >
17      <SpaceStation />
18    </Sentry.ErrorBoundary>
19  );
20}

Kontekst i breadcrumbs w Sentry

Sentry pozwala dodawac kontekst do bledow -- informacje o uzytkowniku, ostatnich akcjach (breadcrumbs) i dodatkowe dane:

1// Ustawienie kontekstu uzytkownika
2Sentry.setUser({
3  id: user.id,
4  email: user.email,
5  username: user.callsign,
6});
7
8// Reczne dodawanie breadcrumbs (slad akcji uzytkownika)
9Sentry.addBreadcrumb({
10  category: 'navigation',
11  message: 'Uzytkownik przeszedl do panelu misji',
12  level: 'info',
13});
14
15// Reczne raportowanie bledu z dodatkowym kontekstem
16Sentry.captureException(error, {
17  extra: {
18    missionId: currentMission.id,
19    moduleState: moduleStatus,
20  },
21});

Customowy hook do logowania błędów

Możesz stworzyc wlasny hook, ktory centralizuje logike logowania:

1function useErrorLogger() {
2  const logError = useCallback((error, context = {}) => {
3    const errorReport = {
4      message: error.message,
5      stack: error.stack,
6      timestamp: new Date().toISOString(),
7      url: window.location.href,
8      ...context,
9    };
10
11    // W produkcji wyslij do serwisu
12    if (process.env.NODE_ENV === 'production') {
13      sendToErrorService(errorReport);
14    }
15
16    // W development loguj do konsoli
17    console.error('[ErrorLogger]', errorReport);
18  }, []);
19
20  return { logError };
21}
22
23// Uzycie w komponencie
24function MissionControl() {
25  const { logError } = useErrorLogger();
26
27  const handleDataFetch = async () => {
28    try {
29      const data = await fetchMissionData();
30      setMissions(data);
31    } catch (error) {
32      logError(error, {
33        component: 'MissionControl',
34        action: 'fetchMissionData',
35      });
36      setError('Nie udalo sie pobrac danych misji');
37    }
38  };
39}

Raportowanie błędów na produkcji

Global error handlers

Oprócz Error Boundaries i try-catch, warto dodac globalne handlery, ktore przechwycą błędy wymykajace sie innym mechanizmom:

1// Globalne przechwytywanie nieprzechwyconych błędów
2window.addEventListener('error', (event) => {
3  logErrorToService({
4    type: 'uncaught_error',
5    message: event.message,
6    filename: event.filename,
7    lineno: event.lineno,
8    colno: event.colno,
9  });
10});
11
12// Globalne przechwytywanie nieobsluzonych Promise rejections
13window.addEventListener('unhandledrejection', (event) => {
14  logErrorToService({
15    type: 'unhandled_rejection',
16    message: event.reason?.message || 'Unknown rejection',
17    stack: event.reason?.stack,
18  });
19});

Poziomy waznosci błędów

Nie wszystkie bledy są równie wazne. Serwisy error tracking pozwalaja na klasyfikacje:

1// Krytyczny blad - aplikacja nie dziala
2Sentry.captureException(error, { level: 'fatal' });
3
4// Blad - funkcjonalnosc nie dziala, ale aplikacja tak
5Sentry.captureException(error, { level: 'error' });
6
7// Ostrzezenie - cos moze byc nie tak
8Sentry.captureMessage('API odpowiada wolno', 'warning');
9
10// Informacja - przydatna do debugowania
11Sentry.captureMessage('Uzytkownik zmienil jezyk', 'info');

Source maps dla debugowania produkcji

Kod produkcyjny jest zminifikowany -- stack trace jest nieczytelny bez source maps. Source maps to jak mapa dekodujaca -- pozwalaja przetlumaczyc pozycje w zminifikowanym kodzie na oryginalne pliki zrodlowe.

1// Bez source maps stack trace wyglada tak:
2// Error at e.render (main.a1b2c3.js:1:45678)
3
4// Z source maps:
5// Error at MissionControl.render (MissionControl.jsx:42:15)

Konfiguracja source maps

1// webpack.config.js
2module.exports = {
3  devtool: 'source-map', // Generuj source maps
4  // ...
5};
6
7// Wazne: source maps NIE powinny byc publiczne!
8// Uploaduj je do Sentry, ale nie serwuj uzytkownikom:
9// sentry-cli sourcemaps upload ./build

Source maps pozwalaja Ci zobaczyc dokladnie w ktorej linii oryginalnego kodu wystapil blad, nawet jesli produkcyjny bundle jest zminifikowany do jednej linii. To jak posiadanie schematu technicznego statku kosmicznego -- zamiast patrzec na niezrozumialy zminifikowany panel, widzisz dokladnie ktory modul zawiodl i dlaczego. Pamietaj jednak, zeby nigdy nie udostepniac source maps publicznie -- to bylby jak udostepnienie planow statku potencjalnym najezdcom.

Przejdź do CodeWorlds