Badamy wykorzystanie Sentry z Reactem.

Ten artykuł jest częścią serii, która zaczyna się od błędów Sentry na przykładzie: .
Implementacja React
Najpierw musimy dodać nowy projekt Sentry dla tej aplikacji; z witryny Sentry. W tym przypadku wybieramy React.
Ponownie implementujemy nasze dwa przyciski, Hello i Error, aplikację w React. Zaczynamy od utworzenia naszej początkowej aplikacji:
npx create-react-app react-appNastępnie importujemy pakiet Sentry:
yarn add @sentry/browseri inicjalizujemy go:
react-app / src / index.js
...
import * as Sentry from '@sentry/browser';
const RELEASE = '0.1.0';
if (process.env.NODE_ENV === 'production') {
Sentry.init({
dsn: 'https://303c04eac89844b5bfc908ceffc6757c@sentry.io/1289887',
release: RELEASE,
});
}
...Obserwacje:
- Podczas rozwoju mamy inne mechanizmy obserwacji problemów, na przykład konsolę, dlatego włączamy Sentry tylko dla produkcyjnych kompilacji.
Następnie implementujemy nasze przyciski Hello i Error i dodajemy je do aplikacji:
react-app / src / Hello.js
import React, { Component } from 'react';
import * as Sentry from '@sentry/browser';
export default class Hello extends Component {
state = {
text: '',
};
render() {
const { text } = this.state;
return (
<div>
<button
onclick="{this.handleClick}"
>
Cześć
</button>
<div>{text}</div>
</div>
)
}
handleClick = () => {
this.setState({
text: 'Hello World',
});
try {
throw new Error('Caught');
} catch (err) {
if (process.env.NODE_ENV !== 'production') {
return;
}
Sentry.captureException(err);
}
}
}react-app / src / MyError.js
import React, { Component } from 'react';
export default class MyError extends Component {
render() {
return (
<div>
<button
onclick="{this.handleClick}"
>
Error
</button>
</div>
)
}
handleClick = () => {
throw new Error('Uncaught');
}
}react-app / src / App.js
...
import Hello from '.\/Hello';
import MyError from '.\/MyError';
class App extends Component {
render() {
return (
<div classname="App">
...
<hello />
<myerror />
</div>
);
}
}
export default App;Problem (Mapy Źródłowe)
Możemy przetestować Sentry z produkcyjną wersją, wpisując:
yarn builda z folderu build wpisujemy:
npx http-server -c-1Problem, z którym natychmiast się spotkamy, polega na tym, że wpisy błędów Sentry odnoszą się do numerów wierszy w zminimalizowanym pakiecie; nie jest to zbyt pomocne.

Usługa Sentry wyjaśnia to, pobierając mapy źródłowe dla zminimalizowanego pakietu po otrzymaniu błędu. W tym przypadku uciekamy z localhosta (niedostępnego dla Sentry).
Rozwiązania (Mapy Źródłowe)
Rozwiązanie tego problemu polega na uruchomieniu aplikacji z publicznego serwera internetowego. Jednym prostym rozwiązaniem jest użycie usługi GitHub Pages (darmowo). Zwykle kroki do wykorzystania są następujące:
Skopiuj zawartość folderu build do folderu docs do głównego katalogu repozytorium.
Włącz GitHub Pages w repozytorium (na GitHubie), aby użyć folderu docs w master gałęzi
Przenieś zmiany na GitHub
Uwaga: po tym, jak zrozumiałem, że muszę użyć create-create-app funkcji strony głównej do uruchomienia aplikacji. Ostatecznie sprowadza się to do dodania następującego do package.json:
"homepage": "https://larkintuckerllc.github.io/hello-sentry/"Ostateczna wersja uruchomionej aplikacji jest dostępna pod adresem:
Ilustracja złapanych błędów
Przejdźmy przez kliknięcie przycisku Hello.

Z błędem, który pojawia się w następujący sposób:

Obserwacje:
- Ten raport o błędzie nie mógł być jaśniejszy, BRAVO.
Ilustracja nieuchwyconych błędów
Podobnie, przejdźmy przez kliknięcie przycisku Error.

Z błędem, który pojawia się w następujący sposób:

Najlepsze przetwarzanie nieuchwyconych błędów (renderowanie)
Wprowadzenie Granic Błędów
Błąd JavaScript w części interfejsu użytkownika nie powinien zakłócać działania całej aplikacji. Aby rozwiązać ten problem dla użytkowników React, React 16 wprowadza nowe pojęcie "granic błędów".
Granice błędów to komponenty React, które przechwytują błędy JavaScript w dowolnym miejscu swojego drzewa komponentów, rejestrują te błędy i wyświetlają zapasowy interfejs użytkownika zamiast uszkodzonego drzewa komponentów. Granice błędów łapią błędy podczas renderowania, w metodach cyklu życia oraz w konstruktorach całego drzewa pod nimi.
…
Nowe zachowanie dla nieuchwyconych błędów
Ta zmiana ma ogromne znaczenie. Począwszy od React 16, błędy, które nie zostały przechwycone przez żadną granicę błędów, spowodują odmontowanie całego drzewa komponentów React.
— Dan Abramov —
Ważne wyjaśnienie, które zajęło mi trochę czasu, zanim je zrozumiałem, polega na tym, że powyższe zachowanie działa tylko w przypadku błędów generowanych w metodzie renderowania (lub, co bardziej prawdopodobne, w którejkolwiek z metod cyklu życia). Na przykład zastosowanie granic błędów nie przyniosłoby żadnych korzyści w przypadku naszej przycisku Error; ten błąd występował w obsłudze kliknięcia.
Stwórzmy przykład błędu renderowania, a następnie użyjmy granic błędów do bardziej eleganckiej obsługi błędów.
react-app / src / MyRenderError
import React, { Component } from 'react';
export default class MyRenderError extends Component {
state = {
flag: false,
};
render() {
const { flag } = this.state;
return (
<div>
<button
onclick="{this.handleClick}"
>
Błąd renderowania
</button>
{ flag && <div>{flag.busted.bogus}</div> }
</div>
)
}
handleClick = () => {
this.setState({
flag: true,
});
}
}Obserwacja:
Po naciśnięciu przycisku, React zostanie wyświetlony flag.busted.bogus, co generuje błąd
Bez granicy błędów całe drzewo komponentów zostanie odmontowane
Następnie piszemy nasz kod granicy błędów (używa nowej metody cyklu życia componentDidCatch); to jest w zasadzie przykład podany w artykule Dana Abramova:
react-app / src / ErrorBoundary.js
import React, { Component } from 'react';
import * as Sentry from '@sentry/browser';
export default class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(err, info) {
this.setState({ hasError: true });
Sentry.captureException(err);
}
render() {
if (this.state.hasError) {
return <h1>Coś poszło nie tak.</h1>;
}
return this.props.children;
}
}Na koniec używamy tego komponentu:
react-app / src / App.js
...import MyRenderError from './MyRenderError';
class App extends Component {
render() {
return (
<errorboundary>
<div classname="App">
...
</div>
</errorboundary>
);
}
}
...W tym przypadku naciśnięcie przycisku Render Error wyświetli zapasowy interfejs użytkownika i zgłosi błąd do Sentry.


Zakończenie
Mam nadzieję, że to było pomocne.
P.S.
P.S. Czatuj na Telegramie o Sentry
Źródło: habr.com
