ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

БСгодня я расскаТу Π²Π°ΠΌ ΠΎΠ± отслСТивании ошибок Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React. ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ внСшнСго интСрфСйса ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для отслСТивания ошибок. НСкоторыС ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ часто ΠΎΡ‚ΠΊΠ»Π°Π΄Ρ‹Π²Π°ΡŽΡ‚ отслСТиваниС ошибок, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡΡΡŒ ΠΊ Π½Π΅ΠΌΡƒ послС Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ, тСстов ΠΈ ΠΏΡ€ΠΎΡ‡Π΅Π³ΠΎ. Однако, Ссли Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ свой ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ Π² Π»ΡƒΡ‡ΡˆΡƒΡŽ сторону, Ρ‚ΠΎ просто сдСлайтС это!

1. Π—Π°Ρ‡Π΅ΠΌ Π²Π°ΠΌ Π½ΡƒΠΆΠ΅Π½ Sentry?

Π― ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°ΡŽ, Ρ‡Ρ‚ΠΎ Π²Ρ‹ заинтСрСсованы Π² отслСТивании ошибок Π² процСссС производства

Π’Ρ‹ Π΄ΡƒΠΌΠ°Π΅Ρ‚Π΅, Ρ‡Ρ‚ΠΎ этого нСдостаточно?

Π₯ΠΎΡ€ΠΎΡˆΠΎ, Π΄Π°Π²Π°ΠΉΡ‚Π΅ посмотрим Π½Π° Π΄Π΅Ρ‚Π°Π»ΠΈ.

ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρ‹ использования Sentry для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ²:

  • ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΈΠ·Π±Π°Π²Π»ΡΡ‚ΡŒΡΡ ΠΎΡ‚ рисков ΠΏΡ€ΠΈ Ρ€Π°Π·Π²Π΅Ρ€Ρ‚Ρ‹Π²Π°Π½ΠΈΠΈ ΠΊΠΎΠ΄Π° с ошибками
  • ΠŸΠΎΠΌΠΎΡ‰ΡŒ QA Π² тСстировании ΠΊΠΎΠ΄Π°
  • ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ быстрых ΡƒΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠΉ ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°Ρ…
  • Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ быстрого исправлСния ошибок
  • ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΡƒΠ΄ΠΎΠ±Π½ΠΎΠ³ΠΎ отобраТСния ошибок Π² Π°Π΄ΠΌΠΈΠ½-ΠΏΠ°Π½Π΅Π»ΠΈ
  • Π‘ΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²ΠΊΠ° ошибок ΠΏΠΎ сСгмСнтам ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ / Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π°

ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρ‹ для CEO / Lead ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°

  • Экономия Π΄Π΅Π½Π΅Π³ (Sentry ΠΌΠΎΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π½Π° Π²Π°ΡˆΠΈΡ… сСрвСрах)
  • ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΎΡ‚Π·Ρ‹Π²ΠΎΠ² ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ
  • ПониманиС Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π½Π΅ Ρ‚Π°ΠΊ с вашим ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠΌ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ
  • ПониманиС количСства ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ, Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‰ΠΈΡ… Ρƒ людСй с вашим ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ
  • ΠŸΠΎΠΌΠΎΡ‰ΡŒ Π² поискС мСст, Π³Π΄Π΅ ваши Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ допустили ΠΎΠΏΠ»ΠΎΡˆΠ½ΠΎΡΡ‚ΡŒ

Π― Π΄ΡƒΠΌΠ°ΡŽ, Ρ‡Ρ‚ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ Π±Ρ‹Π»ΠΈ Π±Ρ‹ заинтСрСсованы Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ Π² ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ. Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ этот список ΠΏΡ€ΠΈΡ‡ΠΈΠ½, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ±Π΅Π΄ΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΡŒΡΡ‚Π²ΠΎ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Sentry.

Π‘ΡƒΠ΄ΡŒΡ‚Π΅ остороТны с послСдним ΠΏΡƒΠ½ΠΊΡ‚ΠΎΠΌ Π² спискС для бизнСса.

Π’Ρ‹ ΡƒΠΆΠ΅ заинтСрСсованы?

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ Sentry?

Sentry – это прилоТСния для отслСТивания ошибок с ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ ΠΎΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Ρ‚ΡŒ, ΠΈΡΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ сбои Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. НС Π·Π°Π±Ρ‹Π²Π°ΠΉΡ‚Π΅ ΠΈ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ позволяСт ΠΏΠΎΠ²Ρ‹ΡˆΠ°Ρ‚ΡŒ эффСктивности ΠΈ ΡƒΠ»ΡƒΡ‡ΡˆΠ°Ρ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ΅ использованиС. Sentry ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ JavaScript, Node, Python, PHP, Ruby, Java ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ языки программирования.

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

2. Π’ΠΎΠΉΠ΄ΠΈΡ‚Π΅ ΠΈ создайтС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚

  • ΠžΡ‚ΠΊΡ€ΠΎΠΉΡ‚Π΅ ваш Sentry Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π²Π°ΠΌ придСтся Π²ΠΎΠΉΡ‚ΠΈ Π² систСму. (ΠžΠ±Ρ€Π°Ρ‰Π°ΡŽ внимаю Ρ‡Ρ‚ΠΎ Sentry ΠΌΠΎΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π½Π° Π²Π°ΡˆΠΈΡ… сСрвСрах)
  • Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ шаг ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚
  • Π’Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ ваш язык ΠΈΠ· списка. (ΠœΡ‹ собираСмся Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ React. НаТмитС Β«Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Β»)

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ 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. Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ React ΠΈ Sentry

Π’Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ npm ΠΏΠ°ΠΊΠ΅Ρ‚ Π² ваш ΠΏΡ€ΠΎΠ΅ΠΊΡ‚.

npm i @sentry/browser

Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ Sentry Π² вашСм ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅:

Sentry.init({
 // dsn: #dsnUrl,
});

DSN находится Π² Projects -> Settings -> Client Keys. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π½Π°ΠΉΡ‚ΠΈ клиСнтскиС ΠΊΠ»ΡŽΡ‡ΠΈ Π² строкС поиска.

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

componentDidCatch(error, errorInfo) {
  Sentry.withScope(scope => {
    Object.keys(errorInfo).forEach(key => {
      scope.setExtra(key, errorInfo[key]);
    });
    Sentry.captureException(error);
 });
}

4. ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π²ΠΎΠΉ ошибки

Π― Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ использовал простоС ΠΌΡƒΠ·Ρ‹ΠΊΠ°Π»ΡŒΠ½ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ с API Deezer. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²ΠΈΠ΄Π΅Ρ‚ΡŒ это здСсь. Нам Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ. Одним ΠΈΠ· способов являСтся ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ свойству "undefined"

ΠœΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΊΠ½ΠΎΠΏΠΊΡƒ, которая Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ 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);

ПослС ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ этой ΠΊΠ½ΠΎΠΏΠΊΠΈ Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΡ€ΠΎΡ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅.

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

Π£ нас Π΅ΡΡ‚ΡŒ пСрвая ошибка

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

Whoo-hoo!

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

Если Π²Ρ‹ Π½Π°ΠΆΠΌΠ΅Ρ‚Π΅ Π½Π° ΠΎΡˆΠΈΠ±ΠΊΡƒ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°, Π²Ρ‹ ΡƒΠ²ΠΈΠ΄ΠΈΡ‚Π΅ трассировку стСка.

ΠžΡ‚ΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ ошибок Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ React с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Sentry

БообщСния выглядят ΠΏΠ»ΠΎΡ…ΠΎ. ΠšΠΎΠ½Π΅Ρ‡Π½ΠΎ, ΠΌΡ‹ Π²ΠΈΠ΄Π΅Π»ΠΈ сообщСния ΠΎΠ± ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ…, Π½Π΅ понимая, Π³Π΄Π΅ этот ΠΊΠΎΠ΄. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ€Π΅Ρ‡ΡŒ ΠΈΠ΄Π΅Ρ‚ ΠΎΠ± исходной ΠΊΠ°Ρ€Ρ‚Π΅ Π² ReactJS, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ Π½Π΅ настроСны.

Π― Ρ‚Π°ΠΊΠΆΠ΅ Ρ…ΠΎΡ‚Π΅Π» Π±Ρ‹ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ инструкции ΠΏΠΎ настройкС исходной ΠΊΠ°Ρ€Ρ‚Ρ‹, Π½ΠΎ это сдСлало Π±Ρ‹ эту ΡΡ‚Π°Ρ‚ΡŒΡŽ Π½Π°ΠΌΠ½ΠΎΠ³ΠΎ Π΄Π»ΠΈΠ½Π½Π΅Π΅, Ρ‡Π΅ΠΌ я ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Π°Π».

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ эту Ρ‚Π΅ΠΌΡƒ здСсь. Если Π²Ρ‹ заинтСрСсованы Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅, Dmitry Nozhenko ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅Ρ‚ Π²Ρ‚ΠΎΡ€ΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ ΠΎΠ± ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ source map. Π˜Ρ‚Π°ΠΊ, Π½Π°ΠΆΠΈΠΌΠ°ΠΉΡ‚Π΅ большС Π»Π°ΠΉΠΊΠΎΠ² ΠΈ ΠΏΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°ΠΉΡ‚Π΅ΡΡŒ Π½Π° Dmitry Nozhenko, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π²Ρ‚ΠΎΡ€ΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ.

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.

β†’ Π’Π΅Π»Π΅Π³Ρ€Π°ΠΌ-Ρ‡Π°Ρ‚ ΠΏΠΎ Sentry

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ