Π‘Π΅Π³ΠΎΠ΄Π½Ρ Ρ ΡΠ°ΡΡΠΊΠ°ΠΆΡ Π²Π°ΠΌ ΠΎΠ± ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠΈ ΠΎΡΠΈΠ±ΠΎΠΊ Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΠΌ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React. ΠΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π²Π½Π΅ΡΠ½Π΅Π³ΠΎ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° ΠΎΠ±ΡΡΠ½ΠΎ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΡ ΠΎΡΠΈΠ±ΠΎΠΊ. ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΡΠ°ΡΡΠΎ ΠΎΡΠΊΠ»Π°Π΄ΡΠ²Π°ΡΡ ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΎΡΠΈΠ±ΠΎΠΊ, Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡΡ ΠΊ Π½Π΅ΠΌΡ ΠΏΠΎΡΠ»Π΅ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, ΡΠ΅ΡΡΠΎΠ² ΠΈ ΠΏΡΠΎΡΠ΅Π³ΠΎ. ΠΠ΄Π½Π°ΠΊΠΎ, Π΅ΡΠ»ΠΈ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡΡ ΡΠ²ΠΎΠΉ ΠΏΡΠΎΠ΄ΡΠΊΡ Π² Π»ΡΡΡΡΡ ΡΡΠΎΡΠΎΠ½Ρ, ΡΠΎ ΠΏΡΠΎΡΡΠΎ ΡΠ΄Π΅Π»Π°ΠΉΡΠ΅ ΡΡΠΎ!
1. ΠΠ°ΡΠ΅ΠΌ Π²Π°ΠΌ Π½ΡΠΆΠ΅Π½ Sentry?
Π― ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Ρ, ΡΡΠΎ Π²Ρ Π·Π°ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠΎΠ²Π°Π½Ρ Π² ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠΈ ΠΎΡΠΈΠ±ΠΎΠΊ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΡΡΠ²Π°
ΠΡ Π΄ΡΠΌΠ°Π΅ΡΠ΅, ΡΡΠΎ ΡΡΠΎΠ³ΠΎ Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ?
Π₯ΠΎΡΠΎΡΠΎ, Π΄Π°Π²Π°ΠΉΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° Π΄Π΅ΡΠ°Π»ΠΈ.
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΏΡΠΈΡΠΈΠ½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Sentry Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ²:
- ΠΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΈΠ·Π±Π°Π²Π»ΡΡΡΡΡ ΠΎΡ ΡΠΈΡΠΊΠΎΠ² ΠΏΡΠΈ ΡΠ°Π·Π²Π΅ΡΡΡΠ²Π°Π½ΠΈΠΈ ΠΊΠΎΠ΄Π° Ρ ΠΎΡΠΈΠ±ΠΊΠ°ΠΌΠΈ
- ΠΠΎΠΌΠΎΡΡ QA Π² ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠΈ ΠΊΠΎΠ΄Π°
- ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π±ΡΡΡΡΡΡ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠΉ ΠΎ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°Ρ
- ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π±ΡΡΡΡΠΎΠ³ΠΎ ΠΈΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΠΎΡΠΈΠ±ΠΎΠΊ
- ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΠ΄ΠΎΠ±Π½ΠΎΠ³ΠΎ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΎΡΠΈΠ±ΠΎΠΊ Π² Π°Π΄ΠΌΠΈΠ½-ΠΏΠ°Π½Π΅Π»ΠΈ
- Π‘ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ ΠΏΠΎ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠ°ΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ / Π±ΡΠ°ΡΠ·Π΅ΡΠ°
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΏΡΠΈΡΠΈΠ½Ρ Π΄Π»Ρ CEO / Lead ΠΏΡΠΎΠ΅ΠΊΡΠ°
- ΠΠΊΠΎΠ½ΠΎΠΌΠΈΡ Π΄Π΅Π½Π΅Π³ (Sentry ΠΌΠΎΠΆΠ½ΠΎ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ Π½Π° Π²Π°ΡΠΈΡ ΡΠ΅ΡΠ²Π΅ΡΠ°Ρ )
- ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΎΡΠ·ΡΠ²ΠΎΠ² ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ
- ΠΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΡΠΎΠ³ΠΎ, ΡΡΠΎ Π½Π΅ ΡΠ°ΠΊ Ρ Π²Π°ΡΠΈΠΌ ΠΏΡΠΎΠ΅ΠΊΡΠΎΠΌ Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ ΡΠ΅Π°Π»ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ
- ΠΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΠΏΡΠΎΠ±Π»Π΅ΠΌ, Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡΡΠΈΡ Ρ Π»ΡΠ΄Π΅ΠΉ Ρ Π²Π°ΡΠΈΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ
- ΠΠΎΠΌΠΎΡΡ Π² ΠΏΠΎΠΈΡΠΊΠ΅ ΠΌΠ΅ΡΡ, Π³Π΄Π΅ Π²Π°ΡΠΈ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π΄ΠΎΠΏΡΡΡΠΈΠ»ΠΈ ΠΎΠΏΠ»ΠΎΡΠ½ΠΎΡΡΡ
Π― Π΄ΡΠΌΠ°Ρ, ΡΡΠΎ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π±ΡΠ»ΠΈ Π±Ρ Π·Π°ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠΎΠ²Π°Π½Ρ Π² ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ Π² ΠΏΠ΅ΡΠ²ΡΡ ΠΎΡΠ΅ΡΠ΅Π΄Ρ. ΠΡ ΡΠ°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΠΎΡ ΡΠΏΠΈΡΠΎΠΊ ΠΏΡΠΈΡΠΈΠ½, ΡΡΠΎΠ±Ρ ΡΠ±Π΅Π΄ΠΈΡΡ Π½Π°ΡΠ°Π»ΡΡΡΠ²ΠΎ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠΎΠ²Π°ΡΡ 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;
}
}
}
Π Sentry Π΅ΡΡΡ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΉ ΠΠ°ΡΡΠ΅Ρ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ Π²Π°ΠΌ ΠΏΠΎΠ½ΡΡΡ, ΡΡΠΎ Π²Ρ Π΄ΠΎΠ»ΠΆΠ½Ρ Π΄Π΅Π»Π°ΡΡ Π΄Π°Π»ΡΡΠ΅. ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ ΡΠ°Π³ΠΈ. Π― Ρ ΠΎΡΡ ΠΏΠΎΠΊΠ°Π·Π°ΡΡ Π²Π°ΠΌ, ΠΊΠ°ΠΊ ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΠ΅ΡΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΎΡΠΈΠ±ΠΎΠΊ. ΠΡΠ»ΠΈΡΠ½ΠΎ, ΠΌΡ ΡΠΎΠ·Π΄Π°Π»ΠΈ ΠΏΡΠΎΠ΅ΠΊΡ! ΠΠ΅ΡΠ΅ΠΉΠ΄Π΅ΠΌ ΠΊ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌΡ ΡΠ°Π³Ρ
3. ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ React ΠΈ Sentry
ΠΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ npm ΠΏΠ°ΠΊΠ΅Ρ Π² Π²Π°Ρ ΠΏΡΠΎΠ΅ΠΊΡ.
npm i @sentry/browser
ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΡΠΉΡΠ΅ Sentry Π² Π²Π°ΡΠ΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ΅:
Sentry.init({
// dsn: #dsnUrl,
});
DSN Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ Π² Projects -> Settings -> Client Keys. ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π½Π°ΠΉΡΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΈΠ΅ ΠΊΠ»ΡΡΠΈ Π² ΡΡΡΠΎΠΊΠ΅ ΠΏΠΎΠΈΡΠΊΠ°.
componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
4. ΠΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠ΅ΡΠ²ΠΎΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ
Π― Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π» ΠΏΡΠΎΡΡΠΎΠ΅ ΠΌΡΠ·ΡΠΊΠ°Π»ΡΠ½ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Ρ API Deezer. ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π²ΠΈΠ΄Π΅ΡΡ ΡΡΠΎ
ΠΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΡΠΎΠ·Π΄Π°ΡΡ ΠΊΠ½ΠΎΠΏΠΊΡ, ΠΊΠΎΡΠΎΡΠ°Ρ Π²ΡΠ·ΡΠ²Π°Π΅Ρ console.log Ρ user.email. ΠΠΎΡΠ»Π΅ ΡΡΠΎΠ³ΠΎ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ ΠΌΡ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅: Uncaught TypeError (Π½Π΅ ΡΠ΄Π°Π΅ΡΡΡ ΠΏΡΠΎΡΠΈΡΠ°ΡΡ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ ΠΈΠ· Π½Π΅ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ 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);
ΠΠΎΡΠ»Π΅ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ ΡΡΠΎΠΉ ΠΊΠ½ΠΎΠΏΠΊΠΈ Π²Ρ Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΏΡΠΎΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ Π΅Π΅ Π² Π±ΡΠ°ΡΠ·Π΅ΡΠ΅.
Π£ Π½Π°Ρ Π΅ΡΡΡ ΠΏΠ΅ΡΠ²Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ°
Whoo-hoo!
ΠΡΠ»ΠΈ Π²Ρ Π½Π°ΠΆΠΌΠ΅ΡΠ΅ Π½Π° ΠΎΡΠΈΠ±ΠΊΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°, Π²Ρ ΡΠ²ΠΈΠ΄ΠΈΡΠ΅ ΡΡΠ°ΡΡΠΈΡΠΎΠ²ΠΊΡ ΡΡΠ΅ΠΊΠ°.
Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π²ΡΠ³Π»ΡΠ΄ΡΡ ΠΏΠ»ΠΎΡ ΠΎ. ΠΠΎΠ½Π΅ΡΠ½ΠΎ, ΠΌΡ Π²ΠΈΠ΄Π΅Π»ΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ°Ρ , Π½Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ, Π³Π΄Π΅ ΡΡΠΎΡ ΠΊΠΎΠ΄. ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΡΠ΅ΡΡ ΠΈΠ΄Π΅Ρ ΠΎΠ± ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠΉ ΠΊΠ°ΡΡΠ΅ Π² 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));
}
});
Π― Ρ ΠΎΡΠ΅Π» Π±Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΎΠ±ΡΡΡ ΡΡΠ½ΠΊΡΠΈΡ Π΄Π»Ρ API catch.
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 ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π²ΡΡΠ°Π²ΠΈΡΡ ΠΎΡΠΈΠ±ΠΊΡ ΡΡΠΎΠ²Π½Ρ Π² ΠΏΠ°Π½Π΅Π»Ρ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³Π° sentry. ΠΠ½ ΠΈΠΌΠ΅Π΅Ρ ΡΠ²ΠΎΠΉΡΡΠ²Π° β βfatalβ, βerrorβ, βwarningβ, βlogβ, βinfo, βdebugβ, βcriticalβ).
- setUser ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ ΡΠΎΡ ΡΠ°Π½ΠΈΡΡ Π»ΡΠ±ΡΠ΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠ΅ Π΄Π°Π½Π½ΡΠ΅ (id, Π°Π΄ΡΠ΅Ρ ΡΠ»Π΅ΠΊΡΡΠΎΠ½Π½ΠΎΠΉ ΠΏΠΎΡΡΡ, ΠΏΠ»Π°Π½ ΠΎΠΏΠ»Π°ΡΡ ΠΈ Ρ. Π΄.).
- setExtra ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π·Π°Π΄Π°ΡΡ Π»ΡΠ±ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅, ΠΊΠΎΡΠΎΡΡΠ΅ Π²Π°ΠΌ Π½ΡΠΆΠ½Ρ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠ°Π³Π°Π·ΠΈΠ½.
ΠΡΠ»ΠΈ Π²Ρ Ρ ΠΎΡΠΈΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈΡΡ ΠΎΡΠ·ΡΠ²Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ ΠΎΠ± ΠΎΡΠΈΠ±ΠΊΠ΅, Π²Π°ΠΌ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΠ½ΠΊΡΠΈΡ showReportDialog.
Sentry.showReportDialog();
ΠΡΠ²ΠΎΠ΄:
Π‘Π΅Π³ΠΎΠ΄Π½Ρ ΠΌΡ ΠΎΠΏΠΈΡΠ°Π»ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Sentry Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ React.
β Π’Π΅Π»Π΅Π³ΡΠ°ΠΌ-ΡΠ°Ρ ΠΏΠΎ
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com