ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ืื ื—ื ื• ื‘ื•ื—ื ื™ื ืืช ื”ืฉื™ืžื•ืฉ ื‘- Sentry ืขื React.

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ืžืืžืจ ื–ื” ื”ื•ื ื—ืœืง ืžืกื“ืจื” ืฉืžืชื—ื™ืœื” ื‘ื“ื™ื•ื•ื— ืขืœ ืฉื’ื™ืื•ืช Sentry ื‘ืืžืฆืขื•ืช ื“ื•ื’ืžื”: ื—ืœืง ืž- 1.

ื™ื™ืฉื•ื ืฉืœ React

ืจืืฉื™ืช ืขืœื™ื ื• ืœื”ื•ืกื™ืฃ ืคืจื•ื™ืงื˜ Sentry ื—ื“ืฉ ืขื‘ื•ืจ ื™ื™ืฉื•ื ื–ื”; ืžืืชืจ Sentry. ื‘ืžืงืจื” ื–ื” ืื ื• ื‘ื•ื—ืจื™ื ื‘-React.

ื ื™ื™ืฉื ืžื—ื“ืฉ ืืช ืฉื ื™ ื”ื›ืคืชื•ืจื™ื ืฉืœื ื•, Hello and 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 ืœื‘ื ื™ื™ืช ื™ื™ืฆื•ืจ

ืœืื—ืจ ืžื›ืŸ ืื ื• ืžื™ื™ืฉืžื™ื ืืช ื›ืคืชื•ืจื™ ื”ืฉืœื•ื ื•ื”ืฉื’ื™ืื” ืฉืœื ื• ื•ืžื•ืกื™ืคื™ื ืื•ืชื ืœืืคืœื™ืงืฆื™ื”:

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 ืžืชื™ื™ื—ืกื•ืช ืœืžืกืคืจื™ ืฉื•ืจื•ืช ื‘ืืฆื•ื•ื” ื”ืžืžื•ื–ืขืจืช; ืœื ืฉื™ืžื•ืฉื™ ื‘ืžื™ื•ื—ื“.

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ืฉื™ืจื•ืช Sentry ืžืกื‘ื™ืจ ื–ืืช ืขืœ ื™ื“ื™ ืžืฉื™ื›ืช ืžืคื•ืช ื”ืžืงื•ืจ ืขื‘ื•ืจ ื”ื—ื‘ื™ืœื” ื”ืžื•ืคื—ืชืช ืœืื—ืจ ืงื‘ืœืช ืฉื’ื™ืื”. ื‘ืžืงืจื” ื–ื” ืื ื• ืคื•ืขืœื™ื ืž-localhost (ืœื ื ื’ื™ืฉ ืขืœ ื™ื“ื™ ืฉื™ืจื•ืช Sentry).

ืคืชืจื•ื ื•ืช (ืžืคื•ืช ืžืงื•ืจ)

ื”ืคืชืจื•ืŸ ืœื‘ืขื™ื” ื–ื• ื”ื•ื ืœื”ืคืขื™ืœ ืืช ื”ืืคืœื™ืงืฆื™ื” ืžืฉืจืช ืื™ื ื˜ืจื ื˜ ืฆื™ื‘ื•ืจื™. ื›ืคืชื•ืจ ืชืฉื•ื‘ื” ืคืฉื•ื˜ ืื—ื“ ืœืฉื™ืžื•ืฉ ื‘ืฉื™ืจื•ืช GitHub Pages (ื—ื™ื ื). ื”ืฉืœื‘ื™ื ืœืฉื™ืžื•ืฉ ื”ื ื‘ื“ืจืš ื›ืœืœ ื›ื“ืœืงืžืŸ:

  1. ื”ืขืชืง ืืช ืชื•ื›ืŸ ื”ืชื™ืงื™ื” ืœึดื‘ื ื•ึนืช ืœืชื™ืงื™ื™ื” Docs ื‘ืกืคืจื™ื™ืช ื”ืฉื•ืจืฉ ืฉืœ ื”ืžืื’ืจ.

  2. ืชื“ืœื™ืง ื“ืคื™ GitHub ื‘ืžืื’ืจ (ืž-GitHub) ื›ื“ื™ ืœื”ืฉืชืžืฉ ื‘ืชื™ืงื™ื™ืช ื”ืžืกืžื›ื™ื ื‘ื” ืื‘ ืขื ืคื™ื

  3. ื“ื—ืฃ ืฉื™ื ื•ื™ื™ื ืœ- GitHub

ืฉื™ื ืœื‘: ืื—ืจื™ ืฉื”ื‘ื ืชื™ ื‘ืžื” ืื ื™ ืฆืจื™ืš ืœื”ืฉืชืžืฉ ืฆื•ืจ-ืฆื•ืจ-ืืคืœื™ืงืฆื™ื” ืคื•ื ืงืฆื™ื™ืช ื“ืฃ ื”ื‘ื™ืช ืœื”ืคืขืœืช ื”ืืคืœื™ืงืฆื™ื”. ื”ืกืชื›ื ืœื”ื•ืกื™ืฃ ืืช ื”ื“ื‘ืจื™ื ื”ื‘ืื™ื ืœ-package.json:

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

ื”ื’ืจืกื” ื”ืกื•ืคื™ืช ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ื”ืคื•ืขืœืช ื–ืžื™ื ื” ื‘ื›ืชื•ื‘ืช:

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

ืื™ื•ืจ ืฉืœ ื‘ืื’ื™ื ื ืชืคืกื™ื

ื‘ื•ื ื ืขื‘ื•ืจ ื“ืจืš ืœื—ื™ืฆื” ืขืœ ื›ืคืชื•ืจ ืฉืœื•ื.

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ืขื ืฉื’ื™ืื” ืฉืžื•ืคื™ืขื” ื›ืš:

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ืชืฆืคื™ื•ืช:

  • ื“ื•ื— ื”ื‘ืื’ ื”ื–ื” ืœื ื™ื›ื•ืœ ืœื”ื™ื•ืช ื‘ืจื•ืจ ื™ื•ืชืจ, BRAVO.

ืื™ื•ืจ ืฉืœ ืฉื’ื™ืื•ืช ืœื ื ืœืงื—ื• ื‘ื—ืฉื‘ื•ืŸ

ื‘ืื•ืคืŸ ื“ื•ืžื”, ื‘ื•ืื• ื ืขื‘ื•ืจ ื“ืจืš ืœื—ื™ืฆืช ื”ื›ืคืชื•ืจ ืฉืึฐื’ึดื™ืึธื”.

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ืขื ืฉื’ื™ืื” ืฉืžื•ืคื™ืขื” ื›ืš:

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ื˜ื™ืคื•ืœ ื˜ื•ื‘ ื™ื•ืชืจ ื‘ืฉื’ื™ืื•ืช ืœื ืžื˜ื•ืคืœื•ืช (ืขื™ื‘ื•ื“)

ื”ืงื“ืžื” ืฉืœ ืžื’ื‘ืœื•ืช ืฉื’ื™ืื”

ืฉื’ื™ืืช JavaScript ื‘ื—ืœืง ืžืžืžืฉืง ื”ืžืฉืชืžืฉ ืœื ืืžื•ืจื” ืœืฉื‘ื•ืจ ืืช ื”ื™ื™ืฉื•ื ื›ื•ืœื•. ื›ื“ื™ ืœืคืชื•ืจ ื‘ืขื™ื” ื–ื• ืขื‘ื•ืจ ืžืฉืชืžืฉื™ React, React 16 ืžืฆื™ื’ ืžื•ืฉื’ ื—ื“ืฉ ืฉื ืงืจื "ื’ื‘ื•ืœื•ืช ืฉื’ื™ืื”".

ื’ื‘ื•ืœื•ืช ืฉื’ื™ืื” ื”ื ืจื›ื™ื‘ื™ React ืฉืชื•ืคืกื™ื ืฉื’ื™ืื•ืช JavaScript ื‘ื›ืœ ืžืงื•ื ื‘ืขืฅ ื”ืจื›ื™ื‘ื™ื ื”ืฆืืฆื ืฉืœื”ื, ืจื•ืฉืžื™ื ืืช ื”ืฉื’ื™ืื•ืช ื”ืœืœื• ื•ืžืฆื™ื’ื™ื ืžืžืฉืง ืžืฉืชืžืฉ ื—ืœื•ืคื™ ื‘ืžืงื•ื ืขืฅ ื”ืจื›ื™ื‘ื™ื ืฉืงืจืก. ื’ื‘ื•ืœื•ืช ืฉื’ื™ืื” ืชื•ืคืกื™ื ืฉื’ื™ืื•ืช ื‘ืžื”ืœืš ืจื™ื ื“ื•ืจ, ื‘ืฉื™ื˜ื•ืช ืžื—ื–ื•ืจ ื—ื™ื™ื ื•ื‘ื‘ื ืื™ื ืฉืœ ื”ืขืฅ ื›ื•ืœื• ืฉืžืชื—ืชื.

...

ื”ืชื ื”ื’ื•ืช ื—ื“ืฉื” ืœืฉื’ื™ืื•ืช ืฉืœื ื–ื•ื”ื•

ื”ืฉื™ื ื•ื™ ื”ื–ื” ื”ื•ื ืžืฉืžืขื•ืชื™. ื”ื—ืœ ืž-React 16, ืฉื’ื™ืื•ืช ืฉืœื ื ืชืคืกื• ื‘ืฉื•ื ื’ื‘ื•ืœ ืฉื’ื™ืื” ื™ื’ืจืžื• ืœื‘ื™ื˜ื•ืœ ื”ื”ืจื›ื‘ื” ืฉืœ ื›ืœ ืขืฅ ื”ืจื›ื™ื‘ื™ื ืฉืœ React.

- ื“ืŸ ืื‘ืจืžื•ื‘ - ื˜ื™ืคื•ืœ ื‘ืฉื’ื™ืื•ืช ื‘-React 16

ื”ื‘ื”ืจื” ื—ืฉื•ื‘ื” ืฉืœืงื— ืœื™ ื–ืžืŸ ืขื“ ืฉื”ื‘ื ืชื™ ืฉื–ื” ื–ื” ื”ื”ืชื ื”ื’ื•ืช ืฉืœืขื™ืœ ืขื•ื‘ื“ืช ืจืง ืขื ืฉื’ื™ืื•ืช ืฉื ื–ืจืงื• ื‘ืฉื™ื˜ืช ื”ืจื™ื ื“ื•ืจ (ืื• ืกื‘ื™ืจ ื™ื•ืชืจ ื‘ื›ืœ ืื—ืช ืžืฉื™ื˜ื•ืช ืžื—ื–ื•ืจ ื”ื—ื™ื™ื). ืœื“ื•ื’ืžื”, ืฉื™ืžื•ืฉ ื‘ื’ื‘ื•ืœื•ืช ืฉื’ื™ืื” ืœื ื™ืขื–ื•ืจ ื‘ื›ืคืชื•ืจ ืฉืœื ื• ืฉืึฐื’ึดื™ืึธื”; ืฉื’ื™ืื” ื–ื• ื”ื™ื™ืชื” ื‘ืžื˜ืคืœ ื”ืงืœื™ืงื™ื.

ื‘ื•ืื• ื ื™ืฆื•ืจ ืฉื’ื™ืืช ืจื™ื ื“ื•ืจ ืœื“ื•ื’ืžื” ื•ืœืื—ืจ ืžื›ืŸ ื ืฉืชืžืฉ ื‘ื’ื‘ื•ืœื•ืช ื”ืฉื’ื™ืื” ื›ื“ื™ ืœื˜ืคืœ ื‘ืฉื’ื™ืื” ื‘ืฆื•ืจื” ื—ื™ื ื ื™ืช ื™ื•ืชืจ.

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.gous, ืžื” ืฉื™ื•ืฆืจ ืฉื’ื™ืื”

  • ืœืœื ื’ื‘ื•ืœ ืฉื’ื™ืื”, ื›ืœ ืขืฅ ื”ืจื›ื™ื‘ื™ื ื™ื•ืกืจ

ืœืื—ืจ ืžื›ืŸ ืื ื• ื›ื•ืชื‘ื™ื ืืช ืงื•ื“ ื’ื‘ื•ืœ ื”ืฉื’ื™ืื” ืฉืœื ื• (ืžืฉืชืžืฉ ื‘ืฉื™ื˜ืช ืžื—ื–ื•ืจ ื”ื—ื™ื™ื ื”ื—ื“ืฉื” componentDidCatch); ื–ื• ื‘ืขืฆื ื”ื“ื•ื’ืžื” ืฉื ื™ืชื ื” ื‘ืžืืžืจื• ืฉืœ ื“ืŸ ืื‘ืจืžื•ื‘:

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>
    );
  }
}
...

ืขื ื–ืืช, ืœื—ื™ืฆื” ืขืœ ื”ืœื—ืฆืŸ Render Error ืžืฆื™ื’ื” ืืช ืžืžืฉืง ื”ืžืฉืชืžืฉ ื”ื—ืœื•ืคื™ ื•ืžื“ื•ื•ื—ืช ืขืœ ืฉื’ื™ืื” ืœ- Sentry.

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ื ื™ื˜ื•ืจ ื–ืงื™ืฃ ืžืจื—ื•ืง ืฉืœ ื‘ืื’ื™ื ื‘ื™ื™ืฉื•ืžื™ React Frontend

ื”ืฉืœืžื”

ืื ื™ ืžืงื•ื•ื” ืฉืžืฆืืช ืืช ื–ื” ืžื•ืขื™ืœ.

ื .ื‘. ืงื™ืฉื•ืจ ืœืžืงื•ืจ

PS Telegram ืฆ'ืื˜ ื“ืจืš Sentry https://t.me/sentry_ru

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”