แแฆแแก แแ แแแขแงแแแ แ แแแแฃแ แแ แแจแ แจแแชแแแแแก แแแแแงแฃแ แแก แแแแแแแแก แจแแกแแฎแแ React แแแแแแแชแแแจแ. แคแ แแแขแแแฃแ แ แแแแแแแชแแ แฉแแแฃแแแแ แแ แแ แแแแแแงแแแแแ แจแแชแแแแแแแก แแแแแงแฃแ แแก แแแแแแแแกแแแแก. แแแแแแ แแ แแแแแแแแ แฎแจแแ แแ แแฉแแ แแแก แจแแชแแแแแแแก แแแแแงแฃแ แแก แแแแแแแแก, แฃแแ แฃแแแแแ แแแก แแแแฃแแแแขแแชแแแก, แขแแกแขแแแแก แแ แ.แจ. แแฃแแชแ, แแฃ แแฅแแแ แจแแแแซแแแแ แจแแชแแแแแ แแฅแแแแ แแ แแแฃแฅแขแ แฃแแแแแกแแแแกแแแ, แแแจแแ แฃแแ แแแแ แแแแแแแแ แแก!
1. แ แแขแแ แแญแแ แแแแแ Sentry?
แแคแแฅแ แแ, แแฅแแแ แแแแแขแแ แแกแแแฃแแ แฎแแ แ แฌแแ แแแแแแก แแ แแก แจแแชแแแแแแแก แแแแแงแฃแ แแก แแแแแแ
แ แแแแ แคแแฅแ แแแ, แแก แแ แแ แแก แกแแแแแ แแกแ?
แแแ แแ, แแแแแ แจแแแฎแแแแ แแแขแแแแแก.
แแแแแแ แ แแแแแแแแ แแแแแแแแแ แแแแกแแแแก Sentry-แแก แแแแแงแแแแแแกแแแแก:
- แกแแจแฃแแแแแแก แแแซแแแแ แแแแแแแ แแแชแแแแ แ แแกแแแแ แจแแชแแแแแแแ แแแแแก แแแแแงแแแแแแกแแก
- แแแแฎแแแ แแ QA แแแแแก แขแแกแขแแ แแแแจแ
- แแแแฆแแ แกแฌแ แแคแ แจแแขแงแแแแแแแแแ แแ แแแแแแแแแก แจแแกแแฎแแ
- แจแแชแแแแแแแก แกแฌแ แแคแแ แแแแแกแฌแแ แแแแก แฃแแแ แ
- แจแแชแแแแแแแก แแแกแแฎแแ แฎแแแแแ แฉแแแแแแแก แแแฆแแแ แแแแแแแกแขแ แแชแแฃแ แแแแแแจแ
- แแแแแแแแ แจแแชแแแแแแ แแแแฎแแแ แแแแแก/แแ แแฃแแแ แแก แกแแแแแแขแแก แแแฎแแแแแ
แแฆแแแกแ แฃแแแแแแ แแแ แแฅแขแแ แแก/แฌแแแงแแแแ แแ แแแฅแขแแก แซแแ แแแแแ แแแแแแแแ
- แแแแแแแ แคแฃแแ (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 แแแแแแ แแแแก แแ แแแฅแขแแแจแ -> แแแ แแแแขแ แแแ -> แแแแแแขแแก แแแกแแฆแแแแแ. แแฅแแแ แจแแแแซแแแแ แแแแแแ แแแแแแขแแก แแแกแแฆแแแแแ แกแแซแแแแ แแแแจแ.
componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
}
4. แแแ แแแแ แจแแชแแแแแก แแแแแงแฃแ แแก แแแแแแแ
แแแแแแแแแ, แแ แแแแแแแงแแแ แแแ แขแแแ แแฃแกแแแแแฃแ แ แแแแแแแชแแ Deezer API-แแ. แแฅแแแ แจแแแแซแแแแ แแแฎแแ แแก
แฉแแแ แฃแแแ แจแแแฅแแแแ แฆแแแแแ, แ แแแแแแช แ แแแแแก แแแแกแแแ.แแแแ ั user.email. แแ แแแฅแแแแแแแก แจแแแแแ แฉแแแ แฃแแแ แแแแแฆแแ แจแแชแแแแแก แจแแขแงแแแแแแแ: Uncapped 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);
แแ แฆแแแแแแก แแแขแแแ แแ แแแแก แจแแแแแ, แแฅแแแ แฃแแแ แจแแแแแฌแแแ แแแ แแ แแฃแแแ แจแ.
แฉแแแ แแแแฅแแก แแแ แแแแ แจแแชแแแแ
แฃแ-แฐแ!
แแฃ แแแแฌแแแแฃแแแแ แกแแแแฃแ แแก แจแแชแแแแแแ, แแแแแแฎแแแ แกแขแแแแก แแแแแก.
แจแแขแงแแแแแแแแแ แชแฃแแแ แแแแแแงแฃแ แแแ. แ แ แแฅแแ แฃแแแ, แฉแแแ แแแแฎแแ แจแแชแแแแแก แจแแขแงแแแแแแแแแ แแแแก แแแแแแแก แแแ แแจแ, แแฃ แกแแ แแ แแก แแแแ. แแแแฃแแแกแฎแแแแแ, แฉแแแ แแกแแฃแแ แแแ ReactJS-แจแ แฌแงแแ แแก แ แฃแแแแ, แ แแแแแ แแกแแแ แแ แแ แแก แแแแคแแแฃแ แแ แแแฃแแ.
แแ แแกแแแ แแกแฃแ แก แแแแแฌแแแแ แแแกแขแ แฃแฅแชแแแแ แฌแงแแ แแก แ แฃแฅแแก แแแกแแงแแแแแแแ, แแแแ แแ แแก แแ แกแขแแขแแแก แแแแ แแ แฃแคแ แ แฎแแแแ แซแแแ แแแฎแแแก, แแแแ แ แแ แแแแแแแแแ.
แจแแแแซแแแแ แจแแแกแฌแแแแแ แแก แแแแ
5. แแแแแแงแแแแ Sentry แแแแ แฌแแ แขแแแแ API
แฒแฒแฒ แฒแฒ. แฏแแแแกแแ แแแขแแก แแแแแแแแแแกแ แแแแแแฎแแแแ แฌแแแ แแแแแชแแแจแ. แแฃแแชแ, แ แแก แแแแแแ 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 แกแแจแฃแแแแแแก แแแซแแแแ แฉแแกแแแ แแแแแก แจแแชแแแแ แกแแแแ แแฏแ แแแคแแจแ. แแแก แแฅแแก แแแแกแแแแแ - 'fatal', 'error', 'แแแคแ แแฎแแแแแ', 'log', 'info, 'debug', 'แแ แแขแแแฃแแ').
- setUser แแฎแแแ แแแ แจแแแแแฎแแก แแแแแกแแแแ แ แแแแฎแแแ แแแแแก แแแแแชแแแแแ (แแแแแขแแคแแแแขแแ แ, แแแแฅแขแ แแแฃแแ แคแแกแขแแก แแแกแแแแ แแ, แแแแแฎแแแก แแแแแ แแ แ.แจ.).
- setExtra แกแแจแฃแแแแแแก แแแซแแแแ แแแฃแแแแแ แแฅแแแแแแแก แกแแญแแ แ แแแแแกแแแแ แ แแแแแชแแแ, แแแแแแแแแ, แจแแแแฎแแ.
แแฃ แแกแฃแ แ แแแแฆแแ แแแแฎแแแ แแแแแก แแแแแฎแแแฃแ แแแ แจแแชแแแแแก แจแแกแแฎแแ, แฃแแแ แแแแแแงแแแแ showReportDialog แคแฃแแฅแชแแ.
Sentry.showReportDialog();
แแแกแแแแ:
แแฆแแก แฉแแแ แแฆแแฌแแ แแ Sentry-แแก React แแแแแแแชแแแจแ แแแขแแแ แแ แแแแก แแ แแ แแแ.
โ Telegram แฉแแขแ แแแแ
แฌแงแแ แ: www.habr.com