ααααααααααα»αααΉαααααΆααα’αααα’αααΈααΆαααΆαααΆαααα α»ααααα»ααααααΆααααααααα αααα»ααααααα·ααΈ React α αααααα·ααΈαααααααΆααα»ααα·αααααΌαααΆαααααΎααΆααααααΆαααααΆααααΆαααΆαααΆαααα α»αααα αααα»αα αα»ααα½αα ααα½αααααααα·αααΆαααΆαααΆαααα α»α ααααααααααα ααΆαα·ααααααΆααααΈα―αααΆα ααΆαααααΎαααααααα αααΆαβααΆβαα·α ααααα·αβααΎβα’αααβα’αΆα βααααΆααβααααΌβαβααα·αααβααααβα’αααβα±ααβααΆααβααβααα’βαααααΎαβαααβααααΆααβααβααααΎβααΆβ!
1. α ααα»α’αααΈααΆαααΆα’αααααααΌαααΆα Sentry?
αααα»αααααααααΆα’αααα αΆααα’αΆαααααααααα»αααΆαααΆαααΆαααα α»αα’αα‘α»ααααααα·α
ααΎα’ααααα·αααΆααααα·ααααααααααΆαααα?
αα·αα’αΈαα αααααΎαααααααΆααααα’α·αα
α ααα»ααααααΌααααααΆααα’αααα’αα·αααααααααα»αααΆαααααΎααααΆαα Sentryα
- α’αα»ααααΆαα±ααα’ααααααααΆαα αΆαα·ααααα αααααΆαααααααΆαααΌααααααΆαααα α»α
- αα½α QA ααΆαα½αααΆαααααΎαααααααΌα
- ααα½αααΆαααΆαααΌαααααΉααα ααα’αααΈαααα αΆ
- αααααααΆααααα»αααΆαααααα α»ααααΆαααΆαααα αα
- ααα½αααΆαααΆααααα αΆαααΆααααα½αααααα α»ααα αααα»αααααΆααααααααααα
- ααααααααα α»αααΆααααααα’αααααααΎααααΆαα/αααααα·ααΈαα»ααα
α ααα»ααα αααααααααΆααααααααααΆααααααα·ααααα·/α’αααααΉαααΆα
- αααααααααΆαα (Sentry α’αΆα ααααΌαααΆαααα‘αΎααα ααΎαααΆαααΈαααααααα’ααα)
- ααα½αααΆαααα·α’αααααααΎ
- ααααααααααΈα’αααΈααααα»αααΆαα½αααααααααααα’ααααααα»ααααααΆααααααα
- ααΆααααααΉαα’αααΈα ααα½ααααα αΆαααααα»αααααΆαααΆαα½ααααααα·ααΈααααα’αααα
- αα½αα’αααααααααααααααααααα’αααα’αα·ααααααααααα’αααααΆαααα α»α
αααα»ααα·αααΆα’αααα’αα·ααααααααΉαα αΆααα’αΆααααααααΎα’ααααααααααΆαα»ααα·αα α’αααααα’αΆα ααααΎαααααΈα ααα»αααααααΎααααΈαααα α»ααααα αΌαα α α αααΆαααααα’αααα±αααα½ααααα αΌα Sentry αααααα
ααΌαααααααααααΆαα½αααΆαα»α α»αααααααα αααα»ααααααΈα’αΆααΈαααααα
ααΎα’αααα αΆααα’αΆααααααα αΎαα¬αα ?
ααΎ Sentry ααΆα’αααΈ?
Sentry ααΊααΆαααααα·ααΈααΆαααΆαααα α»ααααααααΎαα αα ααααα½αα’αααα’αα·ααααααααΆαααΆα αα·ααα½ααα»αααΆαααΆαααααα»ααααααΆαααααααα αα»αααααα ααΆαααααα·ααΈα’αα»ααααΆαα±ααα’ααααααααΎαααααα·αααααΆα αα·ααααααα’αααα·αααααα’αααααααΎααααΆααα Sentry ααΆαααα JavaScript, Node, Python, PHP, Ruby, Java αα·αααΆααΆααααααααααα·ααΈααααααααα
2. α αΌα αα·ααααααΎααααααα
- ααΎαααααΈ Sentry ααααα’αααα α’ααααααα ααααΆααααΌαα αΌαα (ααΌαα αααΆαααΆ Sentry α’αΆα ααααΌαααΆαααα‘αΎααα ααΎαααΆαααΈαααααααα’ααα)
- ααα αΆααααααΆααααΊαααααΎααααααα
- ααααΎαααΎαααΆααΆααααα’αααααΈαααααΈα (ααΎαααΉαααααΎαααΎα ααααα·ααααα α α»α "αααααΎααααααα")
ααααΌααααααα·ααΈααααα’αααααΆαααααα α§ααΆα αααααΆααΌαααααΆααααααααααα αΌα 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. ααΆααα½ααααα αΌαααααα·αααα αα·α 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. ααΆαααΆαααα α»αααααΌα
ααΆα§ααΆα ααα αααα»αααΆαααααΎαααααα·ααΈαααααααΈααΆααααααΆαα½α Deezer APIα α’αααα’αΆα
ααΎαααΆα
ααΎαααααΌααααααΎααααΌαα»ααααα α
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);
αααααΆααααΈαααα αΌααααΌαα»αααα α’ααααα½αααααΆαααααααΆαα αααα»ααααααα·ααΈαα»αααα
ααΎαααΆαααα α»αααααΌαααααααΎαα
α αΌα αΌ!
ααααα·αααΎα’αααα α»α ααΎααα α»αααααααΆ α’αααααΉαααΎαααΆααααα
ααΆαααΎααα α’αΆαααααα ααΆβααΆαβαα·αβααΆααβααΎαβααΆαβααΎαβααΆαβααα α»αβαααβαα·αβαααβααΈβααααααβαααβααΌαβαααβα ααΆαααααΆαααΎα ααΎααααα»ααα·ααΆαα’αααΈαααααΈααααααα αααα»α ReactJS αααααααΆαα·αααααΌαααΆαααααααα ααΆααααααααααα
αααα»αβααβα ααβαααααβααΆαααααΆαβαααααΆααβααΆαβαααααΎαβαααααΈβααααα ααα»ααααβααΆβααΉαβααααΎβα±ααβα’αααααβαααβαααβααΆαβα’αααΈβαααβαααα»αβα ααβααΆαα
α’αααα’αΆα
αα·ααααΆαααααΆααααααα
ααΆαααααΎααααΆαα ααααΆαα ααΆαα½αααΉαα ααα»α αααα αα ααΆα 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 α αΆααα
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));
}
});
};
ααααα·αα·αααααΎααα·ααΈααΆαααααα
- ααααα·αααααα α’αα»ααααΆαα±ααα’ααααααα αΌαααα α»αααααα·ααα½ααα αααα»αααααΆαααααααααααααΆααααααΌαα ααΆααΆααααααααααααααα· - 'fatal', 'error', 'warning', 'log', 'info, 'debug', 'critical') α
- αααααα’αααααααΎααααΆαα αα½ααααααΆαα»ααα·ααααααα’αααααααΎααααΆααααΆαα½α (ααααααααΆαα α’αΆααααααΆαα’ααΈααα αααααΆαααΌααΆααααα)α
- ααααααααααα α’αα»ααααΆαα±ααα’ααααααααΆαααα·ααααααααΆαα½ααααα’αααααααΌαααΆα α§ααΆα ααα αααααΆαα»αα
ααααα·αααΎα’αααα ααααα½αααΆαααα·α’αααααααΎα’αααΈααα α»α α’ααααα½αααααααΎαα»αααΆα showReportDialogα
Sentry.showReportDialog();
ααα ααααΈααααα·ααααΆα:
αααααααααΎαααΆααααααΆα’αααΈαα·ααΈαα½ααααα»αααΆααααα αΌα Sentry αα αααα»ααααααα·ααΈ React α
β Telegram ααααααα
ααααα: www.habr.com