Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

αž™αžΎαž„αž€αŸ†αž–αž»αž„αžŸαŸ’αžœαŸ‚αž„αžšαž€αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ Sentry αž‡αžΆαž˜αž½αž™ ReactαŸ”

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž•αŸ’αž“αŸ‚αž€αž˜αž½αž™αž“αŸƒαžŸαŸŠαŸαžšαžΈαžŠαŸ‚αž›αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαžšαžΆαž™αž€αžΆαžšαžŽαŸαž€αŸ†αž αž»αžŸ Sentry αžŠαŸ„αž™αž”αŸ’αžšαžΎαž§αž‘αžΆαž αžšαžŽαŸαž˜αž½αž™αŸ– αž•αŸ’αž“αŸ‚αž€αž“αŸƒ 1.

αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž”αŸ’αžšαžαž·αž€αž˜αŸ’αž˜

αžŠαŸ†αž”αžΌαž„αž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αž“αŸ’αžαŸ‚αž˜αž‚αž˜αŸ’αžšαŸ„αž„ Sentry αžαŸ’αž˜αžΈαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž“αŸαŸ‡αŸ” αž–αžΈαž‚αŸαž αž‘αŸ†αž–αŸαžš Sentry αŸ” αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸαŸ‡αž™αžΎαž„αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸ React αŸ”

αž™αžΎαž„αž“αžΉαž„αž’αž“αž»αžœαžαŸ’αžαž‘αžΎαž„αžœαž·αž‰αž“αžΌαžœαž”αŸŠαžΌαžαž»αž„αž–αžΈαžšαžšαž”αžŸαŸ‹αž™αžΎαž„αž‚αžΊ Hello αž“αž·αž„ Error αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αžΆαž˜αž½αž™ React αŸ” αž™αžΎαž„αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŠαŸ„αž™αž”αž„αŸ’αž€αžΎαžαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ–

npx create-react-app react-app

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž™αžΎαž„αž“αžΆαŸ†αž…αžΌαž›αž€αž‰αŸ’αž…αž”αŸ‹ SentryαŸ–

yarn add @sentry/browser

αž αžΎαž™αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžœαžΆαŸ–

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://[email protected]/1289887',
    release: RELEASE,
  });
}
...

αž€αžΆαžšαžŸαž„αŸ’αž€αŸαžαŸ–

  • αž€αŸ’αž“αž»αž„αž’αŸ†αž‘αž»αž„αž–αŸαž›αž“αŸƒαž€αžΆαžšαž’αž—αž·αžœαžŒαŸ’αžαž“αŸ αž™αžΎαž„αž˜αžΆαž“αž™αž“αŸ’αžαž€αžΆαžšαž•αŸ’αžŸαŸαž„αž‘αŸ€αžαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž”αž‰αŸ’αž αžΆ αžŠαžΌαž…αž‡αžΆαž€αž»αž„αžŸαžΌαž› αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž™αžΎαž„αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžαŸ‚ Sentry αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž•αž›αž·αžαž€αž˜αŸ’αž˜αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αž™αžΎαž„αž’αž“αž»αžœαžαŸ’αžαž”αŸŠαžΌαžαž»αž„ Hello αž“αž·αž„ Error αžšαž”αžŸαŸ‹αž™αžΎαž„ αž αžΎαž™αž”αž“αŸ’αžαŸ‚αž˜αžœαžΆαž‘αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ–

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}
        >
          Hello
        </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;

αž”αž‰αŸ’αž αžΆ (αž•αŸ‚αž“αž‘αžΈαž”αŸ’αžšαž—αž–)

αž™αžΎαž„αž’αžΆαž…αžŸαžΆαž€αž›αŸ’αž”αž„ Sentry αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž•αž›αž·αžαž€αž˜αŸ’αž˜αžŠαŸ„αž™αž”αž‰αŸ’αž…αžΌαž›αŸ–

yarn build

αž αžΎαž™αž–αžΈαž―αž€αžŸαžΆαžš build αž”αž‰αŸ’αž…αžΌαž›αŸ–

npx http-server -c-1

αž”αž‰αŸ’αž αžΆαžŠαŸ‚αž›αž™αžΎαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž—αŸ’αž›αžΆαž˜αŸ—αž‚αžΊαžαžΆ αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΆαž€αŸ†αž αž»αžŸαžšαž”αžŸαŸ‹ Sentry αžŸαŸ†αžŠαŸ…αž›αžΎαž›αŸαžαž”αž“αŸ’αž‘αžΆαžαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž€αŸ’αžšαž»αž˜αžŠαŸ‚αž›αž”αžΆαž“αž”αž„αŸ’αžšαž½αž˜αžαžΌαž…αŸ” αž˜αž·αž“αž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαžαŸ’αž›αžΆαŸ†αž„αžŽαžΆαžŸαŸ‹αŸ”

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

សេវអ Sentry αž–αž“αŸ’αž™αž›αŸ‹αžšαžΏαž„αž“αŸαŸ‡αžŠαŸ„αž™αž‘αžΆαž‰αž•αŸ‚αž“αž‘αžΈαž”αŸ’αžšαž—αž–αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αž‰αŸ’αž…αž”αŸ‹αž–αŸαžαŸŒαž˜αžΆαž“αžŠαŸ‚αž›αž”αžΆαž“αž€αžΆαžαŸ‹αž”αž“αŸ’αžαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž€αŸ†αž αž»αžŸαŸ” αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸαŸ‡αž™αžΎαž„αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž–αžΈ localhost (αž˜αž·αž“αž’αžΆαž…αž…αžΌαž›αž”αŸ’αžšαžΎαž”αžΆαž“αžŠαŸ„αž™αžŸαŸαžœαžΆ Sentry)αŸ”

αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™ (αž•αŸ‚αž“αž‘αžΈαž”αŸ’αžšαž—αž–)

αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž…αŸ†αž–αŸ„αŸ‡αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αž‚αžΊαžαŸ’αžšαžΌαžœαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž–αžΈαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸαž”αžŽαŸ’αžαžΆαž‰αžŸαžΆαž’αžΆαžšαžŽαŸˆαŸ” αž”αŸŠαžΌαžαž»αž„αž†αŸ’αž›αžΎαž™αžαž”αžŠαŸαžŸαžΆαž˜αž‰αŸ’αž‰αž˜αž½αž™αžŠαžΎαž˜αŸ’αž”αžΈαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜ GitHub Pages (αž₯αžαž‚αž·αžαžαŸ’αž›αŸƒ)αŸ” αž‡αŸ†αž αžΆαž“αž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‡αžΆαž’αž˜αŸ’αž˜αžαžΆαž˜αžΆαž“αžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ–

  1. αž…αž˜αŸ’αž›αž„αž˜αžΆαžαž·αž€αžΆαž“αŸƒαžαžαž―αž€αžŸαžΆαžš αžŸαŸ’αžαžΆαž”αž“αžΆ αž‘αŸ…αžαž αž―αž€αžŸαžΆαžš αž“αŸ…αž€αŸ’αž“αž»αž„αžαž root αž“αŸƒαžƒαŸ’αž›αžΆαŸ†αž„αŸ”

  2. αž”αžΎαž€ αž αŸ’αž‚αžΈαžαž αž”αž‘αŸ†αž–αŸαžšαŸ” αž“αŸ…αž€αŸ’αž“αž»αž„αžƒαŸ’αž›αžΆαŸ†αž„ (αž–αžΈ GitHub) αžŠαžΎαž˜αŸ’αž”αžΈαž”αŸ’αžšαžΎαžαžαž―αž€αžŸαžΆαžšαž“αŸ…αž€αŸ’αž“αž»αž„ មេ αžŸαžΆαžαžΆαŸ”

  3. αž‡αŸ†αžšαž»αž‰αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‘αŸ… GitHub

αž€αžΆαžšαž€αžαŸ‹αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αŸ– αž”αž“αŸ’αž‘αžΆαž”αŸ‹β€‹αž–αžΈβ€‹αžαŸ’αž‰αž»αŸ†β€‹αžšαž€β€‹αžƒαžΎαž‰β€‹αž’αŸ’αžœαžΈβ€‹αžŠαŸ‚αž›β€‹αžαŸ’αž‰αž»αŸ†β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αŸ’αžšαžΎ αž”αž„αŸ’αž€αžΎαž-αž”αž„αŸ’αž€αžΎαž-αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ αž˜αž»αžαž„αžΆαžšαž‘αŸ†αž–αŸαžšαžŠαžΎαž˜ αžŠαžΎαž˜αŸ’αž”αžΈαž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ” αž”αžΆαž“αž…αž»αŸ‡αž˜αž€αžŠαžΎαž˜αŸ’αž”αžΈαž”αž“αŸ’αžαŸ‚αž˜αžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž‘αŸ… package.jsonαŸ–

"homepage": "https://larkintuckerllc.github.io/hello-sentry/"

αž€αŸ†αžŽαŸ‚αž…αž»αž„αž€αŸ’αžšαŸ„αž™αž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ‚αž›αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž˜αžΆαž“αž“αŸ…αŸ–

https://larkintuckerllc.github.io/hello-sentry/

αžšαžΌαž”αž—αžΆαž–αž“αŸƒ Caught Bugs

αžαŸ„αŸ‡β€‹αž…αžΌαž›β€‹αž‘αŸ…β€‹αž…αž»αž…β€‹αž”αŸŠαžΌαžαž»αž„ HelloαŸ”

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αŸ†αž αž»αžŸαž›αŸαž…αž‘αžΎαž„αžŠαžΌαž…αž“αŸαŸ‡αŸ–

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

αž€αžΆαžšαžŸαž„αŸ’αž€αŸαžαŸ–

  • αžšαž”αžΆαž™αž€αžΆαžšαžŽαŸαž€αŸ†αž αž»αžŸαž“αŸαŸ‡αž˜αž·αž“αž’αžΆαž…αž…αŸ’αž”αžΆαžŸαŸ‹αž‡αžΆαž„αž“αŸαŸ‡αž‘αŸ αž”αŸ’αžšαŸ„αž’αžΌ.

αžšαžΌαž”αž—αžΆαž–αž“αŸƒ Unaccounted αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αŸ†αž αž»αžŸ

αžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αŸαŸ‡αžŠαŸ‚αžšαžŸαžΌαž˜αž…αžΌαž›αž‘αŸ…αžαžΆαž˜αžšαž™αŸˆαž€αžΆαžšαž…αž»αž…αž”αŸŠαžΌαžαž»αž„ αž€αŸ†αž αž»αžŸαž€αŸ’αž“αž»αž„αž€αžΆαžš.

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αŸ†αž αž»αžŸαž›αŸαž…αž‘αžΎαž„αžŠαžΌαž…αž“αŸαŸ‡αŸ–

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

αž€αžΆαžšβ€‹αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™β€‹αž€αŸ†αž αž»αžŸβ€‹αžŠαŸ‚αž›β€‹αž˜αž·αž“β€‹αž”αžΆαž“β€‹αž‚αžŽαž“αžΈβ€‹αž”αžΆαž“β€‹αž›αŸ’αž’β€‹αž”αŸ’αžšαžŸαžΎαžš (αž€αžΆαžšβ€‹αž”αž„αŸ’αž αžΆαž‰β€‹)

αžŸαŸαž…αž€αŸ’αžαžΈαž•αŸ’αžαžΎαž˜αž“αŸƒαžŠαŸ‚αž“αž€αŸ†αžŽαžαŸ‹αž€αŸ†αž αž»αžŸ

αž€αŸ†αž αž»αžŸ JavaScript αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€αž“αŸƒαž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž˜αž·αž“αž‚αž½αžšαž”αŸ†αž”αŸ‚αž€αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‘αžΆαŸ†αž„αž˜αžΌαž›αž‘αŸαŸ” αžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ React React 16 αžŽαŸ‚αž“αžΆαŸ†αž“αžΌαžœαž‚αŸ„αž›αž‚αŸ†αž“αž·αžαžαŸ’αž˜αžΈαž αŸ…αžαžΆ "error bounds"αŸ”

αž–αŸ’αžšαŸ†αžŠαŸ‚αž“αž€αŸ†αž αž»αžŸαž‚αžΊαž‡αžΆαžŸαž˜αžΆαžŸαž’αžΆαžαž» React αžŠαŸ‚αž›αž…αžΆαž”αŸ‹αž€αŸ†αž αž»αžŸ JavaScript αž‚αŸ’αžšαž”αŸ‹αž‘αžΈαž€αž“αŸ’αž›αŸ‚αž„αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αŸ‚αž€αž’αžΆαž„αžŸαž˜αžΆαžŸαž—αžΆαž‚αž€αžΌαž“αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸ αž€αžαŸ‹αžαŸ’αžšαžΆαž€αŸ†αž αž»αžŸαž‘αžΆαŸ†αž„αž“αŸ„αŸ‡ αž“αž·αž„αž”αž„αŸ’αž€αžΎαž UI αž‡αŸ†αž“αž½αžŸαž‡αŸ†αž“αž½αžŸαž˜αŸ‚αž€αž’αžΆαž„αžŸαž˜αžΆαžŸαž—αžΆαž‚αžŠαŸ‚αž›αž”αžΆαž“αž‚αžΆαŸ†αž„αŸ” αž–αŸ’αžšαŸ†αžŠαŸ‚αž“αž€αŸ†αž αž»αžŸαž…αžΆαž”αŸ‹αž€αŸ†αž αž»αžŸαž€αŸ†αž‘αž»αž„αž–αŸαž›αž”αž„αŸ’αž αžΆαž‰ αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαžœαžŠαŸ’αžαž‡αžΈαžœαž·αž αž“αž·αž„αž“αŸ…αž€αŸ’αž“αž»αž„αž’αŸ’αž“αž€αžŸαžΆαž„αžŸαž„αŸ‹αžŠαžΎαž˜αžˆαžΎαž‘αžΆαŸ†αž„αž˜αžΌαž›αž“αŸ…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž–αž½αž€αžœαžΆαŸ”

...

αž₯αžšαž·αž™αžΆαž”αžαžαŸ’αž˜αžΈαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αŸ†αž αž»αžŸαžŠαŸ‚αž›αž˜αž·αž“αž”αžΆαž“αžšαž€αžƒαžΎαž‰

αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž“αŸαŸ‡αž‚αžΊαžŸαŸ†αžαžΆαž“αŸ‹αŸ” αž‚αž·αžαžαŸ’αžšαžΉαž˜ React 16 αž€αŸ†αž αž»αžŸαžŠαŸ‚αž›αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΆαž”αŸ‹αž”αžΆαž“αžŠαŸ„αž™αž–αŸ’αžšαŸ†αžŠαŸ‚αž“αž€αŸ†αž αž»αžŸαžŽαžΆαž˜αž½αž™αž“αžΉαž„αž”αžŽαŸ’αžαžΆαž›αž±αŸ’αž™αž˜αŸ‚αž€αž’αžΆαž„αžŸαž˜αžΆαžŸαž—αžΆαž‚ React αž‘αžΆαŸ†αž„αž˜αžΌαž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαž€αž…αŸαž‰αŸ”

- Dan Abramov - αž€αžΆαžšαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž€αŸ†αž αž»αžŸαž€αŸ’αž“αž»αž„αž”αŸ’αžšαžαž·αž€αž˜αŸ’αž˜ ៑៦

αž€αžΆαžšβ€‹αž”αž‰αŸ’αž‡αžΆαž€αŸ‹β€‹αžŠαŸβ€‹αžŸαŸ†αžαžΆαž“αŸ‹β€‹αž˜αž½αž™β€‹αžŠαŸ‚αž›β€‹αž”αžΆαž“β€‹αž…αŸ†αžŽαžΆαž™β€‹αž–αŸαž›β€‹αž˜αž½αž™β€‹αžšαž™αŸˆβ€‹αž˜αž»αž“β€‹αž–αŸαž›β€‹αžαŸ’αž‰αž»αŸ†β€‹αžŠαžΉαž„β€‹αžαžΆβ€‹αž“αŸαŸ‡β€‹αž‡αžΆβ€‹αžšαžΏαž„β€‹αž“αŸ„αŸ‡αŸ” αž₯αžšαž·αž™αžΆαž”αžαžαžΆαž„αž›αžΎαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžαŸ‚αž‡αžΆαž˜αž½αž™αž€αŸ†αž αž»αžŸαžŠαŸ‚αž›αž”αžΆαž“αž”αŸ„αŸ‡αž…αŸ„αž›αž“αŸ…αž€αŸ’αž“αž»αž„αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžαŸ’αžšαž”αž„αŸ’αž αžΆαž‰ (αž¬αž‘αŸ†αž“αž„αž‡αžΆαž“αŸ…αž€αŸ’αž“αž»αž„αžœαž·αž’αžΈαžŽαžΆαž˜αž½αž™αž“αŸƒαžœαžŠαŸ’αžαž‡αžΈαžœαž·αž). αž§αž‘αžΆαž αžšαžŽαŸ αž€αžΆαžšαž”αŸ’αžšαžΎβ€‹αž–αŸ’αžšαŸ†αžŠαŸ‚αž“β€‹αž€αŸ†αž αž»αžŸβ€‹αž“αžΉαž„β€‹αž˜αž·αž“β€‹αž’αŸ’αžœαžΎβ€‹αž’αŸ’αžœαžΈβ€‹αž›αŸ’αž’β€‹αž‡αžΆαž˜αž½αž™β€‹αž“αžΉαž„β€‹αž”αŸŠαžΌαžαž»αž„β€‹αžšαž”αžŸαŸ‹β€‹αž™αžΎαž„β€‹αž‘αŸαŸ” αž€αŸ†αž αž»αžŸαž€αŸ’αž“αž»αž„αž€αžΆαžš; αž€αŸ†αž αž»αžŸαž“αŸαŸ‡αž‚αžΊαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž€αžΆαžšαž…αž»αž…αŸ”

αžαŸ„αŸ‡αž”αž„αŸ’αž€αžΎαžαž§αž‘αžΆαž αžšαžŽαŸαž”αž„αŸ’αž αžΆαž‰αž€αŸ†αž αž»αžŸ αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž”αŸ’αžšαžΎαž–αŸ’αžšαŸ†αžŠαŸ‚αž“αž€αŸ†αž αž»αžŸ αžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž€αŸ†αž αž»αžŸαž€αžΆαž“αŸ‹αžαŸ‚αž›αŸ’αž’

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}
        >
          Render Error
        </button>
        { flag && <div>{flag.busted.bogus}</div> }
      </div>
    )
  }

  handleClick = () => {
    this.setState({
      flag: true,
    });
  }
}

αž€αžΆαžšαžŸαž„αŸ’αž€αŸαžαŸ–

  • αž“αŸ…αž–αŸαž›αž’αŸ’αž“αž€αž…αž»αž…αž”αŸŠαžΌαžαž»αž„, αž”αŸ’αžšαžαž·αž€αž˜αŸ’αž˜ αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰ flag.busted.bogusαžŠαŸ‚αž›αž”αž„αŸ’αž€αžΎαžαž€αŸ†αž αž»αžŸ

  • αž”αžΎαž‚αŸ’αž˜αžΆαž“αž–αŸ’αžšαŸ†αžŠαŸ‚αž“αž€αŸ†αž αž»αžŸαž‘αŸ αž˜αŸ‚αž€αž’αžΆαž„αžŸαž˜αžΆαžŸαž—αžΆαž‚αž‘αžΆαŸ†αž„αž˜αžΌαž›αž“αžΉαž„αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž—αŸ’αž‡αžΆαž”αŸ‹

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž™αžΎαž„αžŸαžšαžŸαŸαžšαž€αžΌαžŠαž–αŸ’αžšαŸ†αžŠαŸ‚αž“αž€αŸ†αž αž»αžŸαžšαž”αžŸαŸ‹αž™αžΎαž„ (αž”αŸ’αžšαžΎαžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžαŸ’αžšαžœαžŠαŸ’αžαž‡αžΈαžœαž·αžαžαŸ’αž˜αžΈαŸ” αžŸαž˜αžΆαžŸαž—αžΆαž‚DidCatch); αž“αŸαŸ‡αž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸαžŸαŸ†αžαžΆαž“αŸ‹αžŠαŸ‚αž›αž˜αžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αžšαž”αžŸαŸ‹ Dan AbramovαŸ–

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>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

αž‘αžΈαž”αŸ†αž•αž»αžαž™αžΎαž„αž”αŸ’αžšαžΎαžŸαž˜αžΆαžŸαž’αžΆαžαž»αž“αŸαŸ‡αŸ–

react-app/src/App.js

...
import MyRenderError from './MyRenderError';

class App extends Component {
  render() {
    return (
      <ErrorBoundary>
        <div className="App">
          ...
        </div>
      </ErrorBoundary>
    );
  }
}
...

αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž€αžΆαžšαž…αž»αž…αž”αŸŠαžΌαžαž»αž„ αž”αž„αŸ’αž αžΆαž‰αž€αŸ†αž αž»αžŸαž”αž„αŸ’αž αžΆαž‰ UI αžαŸ’αžšαž›αž”αŸ‹αž˜αž€αžœαž·αž‰ αž αžΎαž™αžšαžΆαž™αž€αžΆαžšαžŽαŸαž–αžΈαž€αŸ†αž αž»αžŸαž‘αŸ… Sentry αŸ”

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

Sentry αž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž–αžΈαž…αž˜αŸ’αž„αžΆαž™αž“αŸƒαž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ React frontend

αž€αžΆαžšαž”αž‰αŸ’αž…αž”αŸ‹

αžαŸ’αž‰αž»αŸ†αžŸαž„αŸ’αžƒαžΉαž˜αžαžΆαž’αŸ’αž“αž€αž”αžΆαž“αžšαž€αžƒαžΎαž‰αžœαžΆαž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαŸ”

PS αž—αŸ’αž‡αžΆαž”αŸ‹αž‘αŸ…αžŠαžΎαž˜

PS Telegram αž‡αž‡αŸ‚αž€αžαžΆαž˜ Sentry https://t.me/sentry_ru

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹