ΠΠ΅Π½Π΅Ρ ΡΠ΅ Π²ΠΈ ΠΊΠ°ΠΆΠ°ΠΌ Π·Π° ΡΠ»Π΅Π΄Π΅ΡΠ΅ Π½Π° Π³ΡΠ΅ΡΠΊΠΈ Π²ΠΎ ΡΠ΅Π°Π»Π½ΠΎ Π²ΡΠ΅ΠΌΠ΅ Π²ΠΎ Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° React. ΠΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° ΠΎΠ΄ ΠΏΡΠ΅Π΄Π½ΠΈΠΎΡ Π΄Π΅Π» ΠΎΠ±ΠΈΡΠ½ΠΎ Π½Π΅ ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ Π·Π° ΡΠ»Π΅Π΄Π΅ΡΠ΅ Π½Π° Π³ΡΠ΅ΡΠΊΠΈ. ΠΠ΅ΠΊΠΎΠΈ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΡΠ΅ΡΡΠΎ Π³ΠΎ ΠΎΠ΄Π»ΠΎΠΆΡΠ²Π°Π°Ρ ΡΠ»Π΅Π΄Π΅ΡΠ΅ΡΠΎ Π½Π° Π³ΡΠ΅ΡΠΊΠΈ, Π²ΡΠ°ΡΠ°ΡΡΠΈ ΡΠ΅ Π½Π° Π½Π΅Π³ΠΎ ΠΏΠΎ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ°, ΡΠ΅ΡΡΠΎΠ²ΠΈ ΠΈΡΠ½. ΠΠ΅ΡΡΡΠΎΠ°, Π°ΠΊΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΎ ΠΏΡΠΎΠΌΠ΅Π½ΠΈΡΠ΅ Π²Π°ΡΠΈΠΎΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ Π½Π° ΠΏΠΎΠ΄ΠΎΠ±ΡΠΎ, ΡΠΎΠ³Π°Ρ ΡΠ°ΠΌΠΎ Π½Π°ΠΏΡΠ°Π²Π΅ΡΠ΅ Π³ΠΎ ΡΠΎΠ°!
1. ΠΠΎΡΡΠΎ Π²ΠΈ Π΅ ΠΏΠΎΡΡΠ΅Π±Π΅Π½ Sentry?
ΠΡΠ΅ΡΠΏΠΎΡΡΠ°Π²ΡΠ²Π°ΠΌ Π΄Π΅ΠΊΠ° ΡΡΠ΅ Π·Π°ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠΈΡΠ°Π½ΠΈ Π΄Π° ΡΠ»Π΅Π΄ΠΈΡΠ΅ Π³ΡΠ΅ΡΠΊΠΈ Π·Π° Π²ΡΠ΅ΠΌΠ΅ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΡΡΠ²ΠΎΡΠΎ
ΠΠ°Π»ΠΈ ΠΌΠΈΡΠ»ΠΈΡΠ΅ Π΄Π΅ΠΊΠ° ΠΎΠ²Π° Π½Π΅ Π΅ Π΄ΠΎΠ²ΠΎΠ»Π½ΠΎ?
ΠΠΎΠ±ΡΠΎ, Π°ΡΠ΄Π΅ Π΄Π° Π³ΠΈ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌΠ΅ Π΄Π΅ΡΠ°Π»ΠΈΡΠ΅.
ΠΠ»Π°Π²Π½ΠΈΡΠ΅ ΠΏΡΠΈΡΠΈΠ½ΠΈ Π·Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠΈΡΠ΅ Π΄Π° ΠΊΠΎΡΠΈΡΡΠ°Ρ Sentry:
- ΠΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΡΠ΅ ΡΠΈΠ·ΠΈΡΠΈ ΠΏΡΠΈ ΡΠ°ΡΠΏΠΎΡΠ΅Π΄ΡΠ²Π°ΡΠ΅ Π½Π° ΠΊΠΎΠ΄ ΡΠΎ Π³ΡΠ΅ΡΠΊΠΈ
- ΠΠΎΠΌΠΎΠ³Π½Π΅ΡΠ΅ QA ΡΠΎ ΡΠ΅ΡΡΠΈΡΠ°ΡΠ΅ Π½Π° ΠΊΠΎΠ΄ΠΎΡ
- ΠΠΎΠ±ΠΈΠ²Π°ΡΡΠ΅ Π±ΡΠ·ΠΈ ΠΈΠ·Π²Π΅ΡΡΡΠ²Π°ΡΠ° Π·Π° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ
- Π‘ΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ Π·Π° Π±ΡΠ·ΠΎ ΠΊΠΎΡΠΈΠ³ΠΈΡΠ°ΡΠ΅ Π½Π° Π³ΡΠ΅ΡΠΊΠΈΡΠ΅
- ΠΠΎΠ±ΠΈΠ²Π°ΡΠ΅ ΠΏΡΠΈΠ³ΠΎΠ΄Π΅Π½ ΠΏΡΠΈΠΊΠ°Π· Π½Π° Π³ΡΠ΅ΡΠΊΠΈ Π²ΠΎ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΈΠ²Π½ΠΈΠΎΡ ΠΏΠ°Π½Π΅Π»
- Π‘ΠΎΡΡΠΈΡΠ°ΡΡΠ΅ Π³ΠΈ Π³ΡΠ΅ΡΠΊΠΈΡΠ΅ ΠΏΠΎ ΡΠ΅Π³ΠΌΠ΅Π½Ρ ΠΎΠ΄ ΠΊΠΎΡΠΈΡΠ½ΠΈΠΊ/ΠΏΡΠ΅Π»ΠΈΡΡΡΠ²Π°Ρ
ΠΠ»Π°Π²Π½ΠΈΡΠ΅ ΠΏΡΠΈΡΠΈΠ½ΠΈ Π·Π° ΠΈΠ·Π²ΡΡΠ΅Π½ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡ/ΠΠΎΠ΄Π΅ΡΠΊΠΈ ΠΏΡΠΎΠ΅ΠΊΡ
- ΠΠ°ΡΡΠ΅Π΄Π΅ΡΠ΅ ΠΏΠ°ΡΠΈ (Sentry ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ° Π½Π° Π²Π°ΡΠΈΡΠ΅ ΡΠ΅ΡΠ²Π΅ΡΠΈ)
- ΠΠΎΠ±ΠΈΠ²Π°ΡΠ΅ ΠΏΠΎΠ²ΡΠ°ΡΠ½ΠΈ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ ΠΎΠ΄ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈΡΠ΅
- Π Π°Π·Π±ΠΈΡΠ°ΡΠ΅ ΡΡΠΎ Π½Π΅ Π΅ Π²ΠΎ ΡΠ΅Π΄ ΡΠΎ Π²Π°ΡΠΈΠΎΡ ΠΏΡΠΎΠ΅ΠΊΡ Π²ΠΎ ΡΠ΅Π°Π»Π½ΠΎ Π²ΡΠ΅ΠΌΠ΅
- Π Π°Π·Π±ΠΈΡΠ°ΡΠ΅ Π½Π° Π±ΡΠΎΡΠΎΡ Π½Π° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΡΡΠΎ Π»ΡΡΠ΅ΡΠΎ Π³ΠΈ ΠΈΠΌΠ°Π°Ρ ΡΠΎ Π²Π°ΡΠ°ΡΠ° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°
- ΠΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ Π΄Π° Π½Π°ΡΠ΄Π΅ΡΠ΅ ΠΌΠ΅ΡΡΠ° ΠΊΠ°Π΄Π΅ ΡΡΠΎ Π²Π°ΡΠΈΡΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠΈ Π½Π°ΠΏΡΠ°Π²ΠΈΠ»Π΅ Π³ΡΠ΅ΡΠΊΠΈ
ΠΠΈΡΠ»Π°ΠΌ Π΄Π΅ΠΊΠ° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠΈΡΠ΅ ΠΏΡΠ²ΠΎ Π±ΠΈ Π±ΠΈΠ»Π΅ Π·Π°ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠΈΡΠ°Π½ΠΈ Π·Π° ΠΎΠ²ΠΎΡ Π½Π°ΠΏΠΈΡ. ΠΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΡΠΎ ΡΠ°ΠΊΠ° Π΄Π° ΡΠ° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ ΠΎΠ²Π°Π° Π»ΠΈΡΡΠ° Π½Π° ΠΏΡΠΈΡΠΈΠ½ΠΈ Π·Π° Π΄Π° Π³ΠΎ ΡΠ±Π΅Π΄ΠΈΡΠ΅ Π²Π°ΡΠΈΠΎΡ ΡΠ΅Ρ Π΄Π° Π³ΠΎ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠ° Sentry.
ΠΠΈΠ΄Π΅ΡΠ΅ Π²Π½ΠΈΠΌΠ°ΡΠ΅Π»Π½ΠΈ ΡΠΎ ΠΏΠΎΡΠ»Π΅Π΄Π½Π°ΡΠ° ΡΡΠ°Π²ΠΊΠ° ΠΎΠ΄ Π΄Π΅Π»ΠΎΠ²Π½ΠΈΠΎΡ ΡΠΏΠΈΡΠΎΠΊ.
ΠΠ°Π»ΠΈ ΡΡΠ΅ Π²Π΅ΡΠ΅ Π·Π°ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠΈΡΠ°Π½ΠΈ?
Π¨ΡΠΎ Π΅ Π‘Π΅Π½ΡΡΠΈ?
Sentry Π΅ Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° Π·Π° ΡΠ»Π΅Π΄Π΅ΡΠ΅ Π³ΡΠ΅ΡΠΊΠΈ ΡΠΎ ΠΎΡΠ²ΠΎΡΠ΅Π½ ΠΊΠΎΠ΄ ΠΊΠΎΡΠ° ΠΈΠΌ ΠΏΠΎΠΌΠ°Π³Π° Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠΈΡΠ΅ Π΄Π° Π³ΠΈ ΡΠ»Π΅Π΄Π°Ρ ΠΈ ΠΏΠΎΠΏΡΠ°Π²Π°Π°Ρ ΠΏΠ°Π΄ΠΎΠ²ΠΈΡΠ΅ Π²ΠΎ ΡΠ΅Π°Π»Π½ΠΎ Π²ΡΠ΅ΠΌΠ΅. ΠΠ΅ Π·Π°Π±ΠΎΡΠ°Π²Π°ΡΡΠ΅ Π΄Π΅ΠΊΠ° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° ΡΠ° Π·Π³ΠΎΠ»Π΅ΠΌΠΈΡΠ΅ Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎΡΡΠ° ΠΈ Π΄Π° Π³ΠΎ ΠΏΠΎΠ΄ΠΎΠ±ΡΠΈΡΠ΅ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΎΡΠΎ ΠΈΡΠΊΡΡΡΠ²ΠΎ. Sentry ΠΏΠΎΠ΄Π΄ΡΠΆΡΠ²Π° JavaScript, Node, Python, PHP, Ruby, Java ΠΈ Π΄ΡΡΠ³ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΡΠΊΠΈ ΡΠ°Π·ΠΈΡΠΈ.
2. ΠΠ°ΡΠ°Π²Π΅ΡΠ΅ ΡΠ΅ ΠΈ ΠΊΡΠ΅ΠΈΡΠ°ΡΡΠ΅ ΠΏΡΠΎΠ΅ΠΊΡ
- ΠΡΠ²ΠΎΡΠ΅ΡΠ΅ ΡΠ° Π²Π°ΡΠ°ΡΠ° ΡΠΌΠ΅ΡΠΊΠ° Π½Π° Sentry. ΠΠΎΠΆΠ΅Π±ΠΈ ΡΠ΅ ΡΡΠ΅Π±Π° Π΄Π° ΡΠ΅ Π½Π°ΡΠ°Π²ΠΈΡΠ΅. (ΠΠ΅ ΠΌΠΎΠ»ΠΈΠΌΠ΅ ΠΈΠΌΠ°ΡΡΠ΅ ΠΏΡΠ΅Π΄Π²ΠΈΠ΄ Π΄Π΅ΠΊΠ° Sentry ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ° Π½Π° Π²Π°ΡΠΈΡΠ΅ ΡΠ΅ΡΠ²Π΅ΡΠΈ)
- Π‘Π»Π΅Π΄Π½ΠΈΠΎΡ ΡΠ΅ΠΊΠΎΡ Π΅ Π΄Π° ΡΠ΅ ΡΠΎΠ·Π΄Π°Π΄Π΅ ΠΏΡΠΎΠ΅ΠΊΡ
- ΠΠ·Π±Π΅ΡΠ΅ΡΠ΅ Π³ΠΎ Π²Π°ΡΠΈΠΎΡ ΡΠ°Π·ΠΈΠΊ ΠΎΠ΄ ΡΠΏΠΈΡΠΎΠΊΠΎΡ. (ΠΠ΅ ΠΈΠ·Π±Π΅ΡΠ΅ΠΌΠ΅ React. ΠΠ»ΠΈΠΊΠ½Π΅ΡΠ΅ Π½Π° βΠΡΠ΅ΠΈΡΠ°Ρ ΠΏΡΠΎΠ΅ΠΊΡβ)
ΠΡΠΈΠ»Π°Π³ΠΎΠ΄Π΅ΡΠ΅ ΡΠ° Π²Π°ΡΠ°ΡΠ° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°. ΠΡΠ½ΠΎΠ²Π΅Π½ ΠΏΡΠΈΠΌΠ΅Ρ Π·Π° ΡΠΎΠ° ΠΊΠ°ΠΊΠΎ Π΄Π° ΡΠ΅ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠ° Sentry Π²ΠΎ ΠΊΠΎΠ½ΡΠ΅ΡΠ½Π΅Ρ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π²ΠΈΠ΄ΠΈ ΠΏΠΎΠ΄ΠΎΠ»Ρ:
import * as Sentry from '@sentry/browser';
// Sentry.init({
// dsn: "<https://[email protected]/1432138>"
// });
// should have been called before using it here
// ideally before even rendering your react app
class ExampleBoundary extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
componentDidCatch(error, errorInfo) {
this.setState({ error });
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
render() {
if (this.state.error) {
//render fallback UI
return (
<a onClick={() => Sentry.showReportDialog()}>Report feedback</a>
);
} else {
//when there's not an error, render children untouched
return this.props.children;
}
}
}
Π‘Π΅Π½ΡΡΠΈ ΠΈΠΌΠ° ΠΊΠΎΡΠΈΡΠ΅Π½ ΠΠΎΠ»ΡΠ΅Π±Π½ΠΈΠΊ ΠΊΠΎΡ ΡΠ΅ Π²ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ Π΄Π° ΡΡΠ°ΡΠΈΡΠ΅ ΡΡΠΎ ΡΡΠ΅Π±Π° Π΄Π° ΠΏΡΠ°Π²ΠΈΡΠ΅ ΡΠ»Π΅Π΄Π½ΠΎ. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΈ ΡΠ»Π΅Π΄ΠΈΡΠ΅ ΠΎΠ²ΠΈΠ΅ ΡΠ΅ΠΊΠΎΡΠΈ. Π‘Π°ΠΊΠ°ΠΌ Π΄Π° Π²ΠΈ ΠΏΠΎΠΊΠ°ΠΆΠ°ΠΌ ΠΊΠ°ΠΊΠΎ Π΄Π° Π³ΠΎ ΠΊΡΠ΅ΠΈΡΠ°ΡΠ΅ Π²Π°ΡΠΈΠΎΡ ΠΏΡΠ² ΡΠΏΡΠ°Π²ΡΠ²Π°Ρ ΡΠΎ Π³ΡΠ΅ΡΠΊΠΈ. ΠΠ΄Π»ΠΈΡΠ½ΠΎ, ΡΠΎΠ·Π΄Π°Π΄ΠΎΠ²ΠΌΠ΅ ΠΏΡΠΎΠ΅ΠΊΡ! ΠΡΠ΄Π΅ Π΄Π° ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΠΌΠ΅ Π½Π° ΡΠ»Π΅Π΄Π½ΠΈΠΎΡ ΡΠ΅ΠΊΠΎΡ
3. ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡΠ° Π½Π° React ΠΈ Sentry
ΠΠΎΡΠ° Π΄Π° Π³ΠΎ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠΎΡ npm Π²ΠΎ Π²Π°ΡΠΈΠΎΡ ΠΏΡΠΎΠ΅ΠΊΡ.
npm i @sentry/browser
ΠΠ½ΠΈΡΠΈΡΠ°Π»ΠΈΠ·ΠΈΡΠ°ΡΡΠ΅ Π³ΠΎ Sentry Π²ΠΎ Π²Π°ΡΠΈΠΎΡ ΠΊΠΎΠ½ΡΠ΅ΡΠ½Π΅Ρ:
Sentry.init({
// dsn: #dsnUrl,
});
DSN ΡΠ΅ Π½Π°ΠΎΡΠ° Π²ΠΎ ΠΡΠΎΠ΅ΠΊΡΠΈ -> ΠΠΎΡΡΠ°Π²ΠΊΠΈ -> ΠΠ»ΠΈΠ΅Π½ΡΡΠΊΠΈ ΠΊΠ»ΡΡΠ΅Π²ΠΈ. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΈ Π½Π°ΡΠ΄Π΅ΡΠ΅ ΠΊΠ»ΡΡΠ΅Π²ΠΈΡΠ΅ Π½Π° ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΡ Π²ΠΎ Π»Π΅Π½ΡΠ°ΡΠ° Π·Π° ΠΏΡΠ΅Π±Π°ΡΡΠ²Π°ΡΠ΅.
componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
4. Π‘Π»Π΅Π΄Π΅ΡΠ΅ Π½Π° ΠΏΡΠ²Π°ΡΠ° Π³ΡΠ΅ΡΠΊΠ°
ΠΠ° ΠΏΡΠΈΠΌΠ΅Ρ, ΠΊΠΎΡΠΈΡΡΠ΅Π² Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½Π° ΠΌΡΠ·ΠΈΡΠΊΠ° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° ΡΠΎ Deezer API. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΎ Π²ΠΈΠ΄ΠΈΡΠ΅
Π’ΡΠ΅Π±Π° Π΄Π° ΡΠΎΠ·Π΄Π°Π΄Π΅ΠΌΠ΅ ΠΊΠΎΠΏΡΠ΅ ΡΡΠΎ ΠΏΠΎΠ²ΠΈΠΊΡΠ²Π° ΠΊΠΎΠ½Π·ΠΎΠ»Π°.Π»ΠΎΠ³ Ρ ΠΊΠΎΡΠΈΡΠ½ΠΈΠΊ.Π΅-ΠΏΠΎΡΡΠ°. ΠΠΎ ΠΎΠ²Π°Π° Π°ΠΊΡΠΈΡΠ° ΡΡΠ΅Π±Π° Π΄Π° Π΄ΠΎΠ±ΠΈΠ΅ΠΌΠ΅ ΠΏΠΎΡΠ°ΠΊΠ° Π·Π° Π³ΡΠ΅ΡΠΊΠ°: ΠΠ΅ΡΠ°ΡΠ΅Π½ ΡΠΈΠΏ ΠΡΠ΅ΡΠΊΠ° (Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠΈΡΠ° ΡΠ²ΠΎΡΡΡΠ²ΠΎ ΠΎΠ΄ Π½Π΅Π΄Π΅ΡΠΈΠ½ΠΈΡΠ°Π½ΠΎ email
) ΠΏΠΎΡΠ°Π΄ΠΈ Π½Π΅Π΄ΠΎΡΡΠ°ΡΡΠ²Π° ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈ ΠΎΠ±ΡΠ΅ΠΊΡ. ΠΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΡΠΎ ΡΠ°ΠΊΠ° Π΄Π° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ ΠΡΠΊΠ»ΡΡΠΎΠΊ ΠΎΠ΄ Javascript.
<button type="button" onClick={() => console.log(user.email)}>
Test Error button
</button>
Π¦Π΅Π»ΠΈΠΎΡ ΠΊΠΎΠ½ΡΠ΅ΡΠ½Π΅Ρ ΠΈΠ·Π³Π»Π΅Π΄Π° Π²Π°ΠΊΠ°:
import React, { Component } from "react";
import { connect } from "react-redux";
import { Input, List, Skeleton, Avatar } from "antd";
import * as Sentry from "@sentry/browser";
import getList from "../store/actions/getList";
const Search = Input.Search;
const mapState = state => ({
list: state.root.list,
loading: state.root.loading
});
const mapDispatch = {
getList
};
class Container extends Component {
constructor(props) {
super(props);
Sentry.init({
dsn: "https://[email protected]/1417586",
});
}
componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
render() {
const { list, loading, getList } = this.props;
const user = undefined;
return (
<div className="App">
<button
type="button"
onClick={() => console.log(user.email)}
>
test error1
</button>
<div onClick={() => Sentry.showReportDialog()}>Report feedback1</div>
<h1>Music Finder</h1>
<br />
<Search onSearch={value => getList(value)} enterButton />
{loading && <Skeleton avatar title={false} loading={true} active />}
{!loading && (
<List
itemLayout="horizontal"
dataSource={list}
locale={{ emptyText: <div /> }}
renderItem={item => (
<List.Item>
<List.Item.Meta
avatar={<Avatar src={item.artist.picture} />}
title={item.title}
description={item.artist.name}
/>
</List.Item>
)}
/>
)}
</div>
);
}
}
export default connect(
mapState,
mapDispatch
)(Container);
ΠΡΠΊΠ°ΠΊΠΎ ΡΠ΅ Π³ΠΎ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠ°ΡΠ΅ ΠΎΠ²Π° ΠΊΠΎΠΏΡΠ΅, ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΎ ΡΠ΅ΡΡΠΈΡΠ°ΡΠ΅ Π²ΠΎ ΠΏΡΠ΅Π»ΠΈΡΡΡΠ²Π°ΡΠΎΡ.
ΠΠ° ΠΈΠΌΠ°ΠΌΠ΅ ΠΏΡΠ²Π°ΡΠ° Π³ΡΠ΅ΡΠΊΠ°
Π£Ρ-Ρ Ρ!
ΠΠΊΠΎ ΠΊΠ»ΠΈΠΊΠ½Π΅ΡΠ΅ Π½Π° Π³ΡΠ΅ΡΠΊΠ°ΡΠ° Π²ΠΎ Π·Π°Π³Π»Π°Π²ΠΈΠ΅ΡΠΎ, ΡΠ΅ Π²ΠΈΠ΄ΠΈΡΠ΅ ΡΡΠ°Π³Π° Π½Π° ΡΡΠ΅ΠΊ.
ΠΠΎΡΠ°ΠΊΠΈΡΠ΅ ΠΈΠ·Π³Π»Π΅Π΄Π°Π°Ρ Π»ΠΎΡΠΎ. Π‘Π΅ ΡΠ°Π·Π±ΠΈΡΠ°, Π²ΠΈΠ΄ΠΎΠ²ΠΌΠ΅ ΠΏΠΎΡΠ°ΠΊΠΈ Π·Π° Π³ΡΠ΅ΡΠΊΠ° Π±Π΅Π· Π΄Π° ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌΠ΅ ΠΊΠ°Π΄Π΅ Π΅ ΠΊΠΎΠ΄ΠΎΡ. Π‘ΡΠ°Π½Π΄Π°ΡΠ΄Π½ΠΎ Π·Π±ΠΎΡΡΠ²Π°ΠΌΠ΅ Π·Π° ΠΌΠ°ΠΏΠ°ΡΠ° Π½Π° ΠΈΠ·Π²ΠΎΡΠΎΡ Π²ΠΎ ReactJS Π±ΠΈΠ΄Π΅ΡΡΠΈ ΡΠΈΠ΅ Π½Π΅ ΡΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΠ°Π½ΠΈ.
ΠΡΡΠΎ ΡΠ°ΠΊΠ°, Π±ΠΈ ΡΠ°ΠΊΠ°Π» Π΄Π° Π΄Π°Π΄Π°ΠΌ ΠΈΠ½ΡΡΡΡΠΊΡΠΈΠΈ Π·Π° ΠΏΠΎΡΡΠ°Π²ΡΠ²Π°ΡΠ΅ Π½Π° ΠΈΠ·Π²ΠΎΡΠ½Π°ΡΠ° ΠΌΠ°ΠΏΠ°, Π½ΠΎ ΡΠΎΠ° Π±ΠΈ ΡΠ° Π½Π°ΠΏΡΠ°Π²ΠΈΠ»ΠΎ ΠΎΠ²Π°Π° ΡΡΠ°ΡΠΈΡΠ° ΠΌΠ½ΠΎΠ³Ρ ΠΏΠΎΠ΄ΠΎΠ»Π³Π° ΠΎΡΠΊΠΎΠ»ΠΊΡ ΡΡΠΎ ΠΈΠΌΠ°Π² Π½Π°ΠΌΠ΅ΡΠ°.
ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠ° ΠΏΡΠΎΡΡΡΠ²Π°ΡΠ΅ ΠΎΠ²Π°Π° ΡΠ΅ΠΌΠ°
5. Π£ΠΏΠΎΡΡΠ΅Π±Π° Sentry ΡΠΎ ΠΊΡΠ°ΡΠ½Π° ΡΠΎΡΠΊΠ° API
ΠΠΠΠ Π. ΠΠΎ ΠΎΠΏΡΠ°ΡΠΈΠ²ΠΌΠ΅ javascript ΠΈΡΠΊΠ»ΡΡΠΎΠΊΠΎΡ Π²ΠΎ ΠΏΡΠ΅ΡΡ ΠΎΠ΄Π½ΠΈΡΠ΅ ΠΏΠ°ΡΠ°Π³ΡΠ°ΡΠΈ. Π‘Π΅ΠΏΠ°ΠΊ, ΡΡΠΎ ΡΠ΅ ΠΏΡΠ°Π²ΠΈΠΌΠ΅ ΡΠΎ XHR Π³ΡΠ΅ΡΠΊΠΈΡΠ΅?
Sentry ΠΈΡΡΠΎ ΡΠ°ΠΊΠ° ΠΈΠΌΠ° ΠΏΡΠΈΠ»Π°Π³ΠΎΠ΄Π΅Π½ΠΎ ΡΠΏΡΠ°Π²ΡΠ²Π°ΡΠ΅ ΡΠΎ Π³ΡΠ΅ΡΠΊΠΈ. ΠΠΎ ΠΊΠΎΡΠΈΡΡΠ΅Π² Π·Π° ΡΠ»Π΅Π΄Π΅ΡΠ΅ Π½Π° API Π³ΡΠ΅ΡΠΊΠΈ.
Sentry.captureException(err)
ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΎ ΠΏΡΠΈΠ»Π°Π³ΠΎΠ΄ΠΈΡΠ΅ ΠΈΠΌΠ΅ΡΠΎ Π½Π° Π³ΡΠ΅ΡΠΊΠ°ΡΠ°, Π½ΠΈΠ²ΠΎΡΠΎ, Π΄Π° Π΄ΠΎΠ΄Π°Π²Π°ΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ, Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½ΠΈ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΊΠΎΡΠΈΡΡΠ΅ΡΡΠΈ ΡΠ° Π²Π°ΡΠ°ΡΠ° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°, Π΅-ΠΏΠΎΡΡΠ° ΠΈΡΠ½.
superagent
.get(`https://deezerdevs-deezer.p.rapidapi.com/search?q=${query}`)
.set("X-RapidAPI-Key", #id_key)
.end((err, response) => {
if (err) {
Sentry.configureScope(
scope => scope
.setUser({"email": "[email protected]"})
.setLevel("Error")
);
return Sentry.captureException(err);
}
if (response) {
return dispatch(setList(response.body.data));
}
});
ΠΠΈ ΡΠ°ΠΊΠ°Π» Π΄Π° ΠΊΠΎΡΠΈΡΡΠ°ΠΌ Π³Π΅Π½Π΅ΡΠΈΡΠΊΠ° ΡΡΠ½ΠΊΡΠΈΡΠ° Π·Π° catch API.
import * as Sentry from "@sentry/browser";
export const apiCatch = (error, getState) => {
const store = getState();
const storeStringify = JSON.stringify(store);
const { root: { user: { email } } } = store;
Sentry.configureScope(
scope => scope
.setLevel("Error")
.setUser({ email })
.setExtra("store", storeStringify)
);
// Sentry.showReportDialog(); - If you want get users feedback on error
return Sentry.captureException(error);
};
Π£Π²Π΅Π·Π΅ΡΠ΅ ΡΠ° ΠΎΠ²Π°Π° ΡΡΠ½ΠΊΡΠΈΡΠ° Π²ΠΎ Π²Π°ΡΠΈΠΎΡ api ΠΏΠΎΠ²ΠΈΠΊ.
export default query => (dispatch, getState) => {
superagent
.get(`https://deezerdevs-deezer.p.rapidapi.com/search?q=${query}`)
.set("X-RapidAPI-Key", #id_key)
.end((error, response) => {
if (error) {
return apiCatch(error, getState)
}
if (response) {
return dispatch(setList(response.body.data));
}
});
};
ΠΡΠ΄Π΅ Π΄Π° Π³ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌΠ΅ ΠΌΠ΅ΡΠΎΠ΄ΠΈΡΠ΅:
- setLevel Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° Π²ΠΌΠ΅ΡΠ½Π΅ΡΠ΅ Π³ΡΠ΅ΡΠΊΠ° Π²ΠΎ Π½ΠΈΠ²ΠΎΡΠΎ Π²ΠΎ ΠΊΠΎΠ½ΡΡΠΎΠ»Π½Π°ΡΠ° ΡΠ°Π±Π»Π° Π½Π° ΡΡΡΠ°ΠΆΠ°Ρ. ΠΠΌΠ° ΡΠ²ΠΎΡΡΡΠ²Π° - βΡΠ°ΡΠ°Π»Π½Π°β, βΠ³ΡΠ΅ΡΠΊΠ°β, βΠΏΡΠ΅Π΄ΡΠΏΡΠ΅Π΄ΡΠ²Π°ΡΠ΅β, βΠ»ΠΎΠ³β, βΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈβ, βΠ΄Π΅Π±Π°Π³ΠΈΡΠ°ΡΠ΅β, βΠΊΡΠΈΡΠΈΡΠ½Π°β).
- setUser ΠΏΠΎΠΌΠ°Π³Π° Π΄Π° ΡΠ΅ Π·Π°ΡΡΠ²Π°Π°Ρ ΠΊΠ°ΠΊΠ²ΠΈ Π±ΠΈΠ»ΠΎ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ (ΠΈΠ΄, Π°Π΄ΡΠ΅ΡΠ° Π½Π° Π΅-ΠΏΠΎΡΡΠ°, ΠΏΠ»Π°Π½ Π·Π° ΠΏΠ»Π°ΡΠ°ΡΠ΅ ΠΈΡΠ½.).
- setExtra Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° Π½Π°Π²Π΅Π΄Π΅ΡΠ΅ ΠΊΠ°ΠΊΠ²ΠΈ Π±ΠΈΠ»ΠΎ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΡΠΎ Π²ΠΈ ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±Π½ΠΈ, Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ, ΡΠΊΠ»Π°Π΄ΠΈΡΠ°ΡΠ΅.
ΠΠΊΠΎ ΡΠ°ΠΊΠ°ΡΠ΅ Π΄Π° Π΄ΠΎΠ±ΠΈΠ²Π°ΡΠ΅ ΠΏΠΎΠ²ΡΠ°ΡΠ½ΠΈ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ ΠΎΠ΄ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈΡΠ΅ Π·Π° Π³ΡΠ΅ΡΠΊΠ°, ΡΡΠ΅Π±Π° Π΄Π° ΡΠ° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° showReportDialog.
Sentry.showReportDialog();
ΠΠ°ΠΊΠ»ΡΡΠΎΠΊ:
ΠΠ΅Π½Π΅Ρ ΠΎΠΏΠΈΡΠ°Π²ΠΌΠ΅ Π΅Π΄Π΅Π½ Π½Π°ΡΠΈΠ½ Π·Π° ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠ°ΡΠ΅ Π½Π° Sentry Π²ΠΎ Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° React.
β Π’Π΅Π»Π΅Π³ΡΠ°ΠΌΡΠΊΠΈ ΡΠ°Π·Π³ΠΎΠ²ΠΎΡ ΠΎΠ΄
ΠΠ·Π²ΠΎΡ: www.habr.com