ReactのエラートラッキングにBugsnagを使う

こんにちはかみむらです。半実験的にフロントエンド(React)のエラートラッキングに、Bugsnagを導入してみました。

そもそもなぜエラートラッキングを必要とするのでしょうか?

ほとんどのアプリケーションでは、障害による機会損失を避けるため最良の設計をします。しかし、現実には障害の起きない完璧なアプリケーションはありません。そのため、いつどこでどんな障害が起きているのか、いち早く気付ける仕組み作りが必要です。


そこで、Bugsnagの登場です。Bugsnagではエラーログを収集できるほか、GitHubのissueと連携できたり、Slackに通知できたりします。そのため、障害が起きたときに対処しやすい設定をすることができます。

他にも、エラートラッキングできるサービスにはSentryというものがあります。Bugsnagと比べ、Sentryの方が知名度がある印象です。
sentry.io

Bugsnagのドキュメントはこちら
docs.bugsnag.com

Sentryの導入はこちらの記事でも書いています。
code-log.hatenablog.com

料金体系

ブログの執筆時(2020年1月3日)では、ライトプラン、スタンダードプラン、エンタープライズプランの3つがあります。ライトプランは無料で使えるので、個人で試すハードルが低いですね。スタンダードプランは59ドル、エンタープライズプランは見積もりといった形です。
www.bugsnag.com

プロジェクトの作成

アカウントの作成後、プロジェクトを作成します。Browserを選択してください。
f:id:kamimura-dev:20200103140203p:plain

そして、Reactを選択します。

f:id:kamimura-dev:20200103140320p:plain

アプリケーションの名前はお好きな名前で大丈夫です。

f:id:kamimura-dev:20200103140358p:plain

アプリケーションの作成

create-react-appをベースにしていきます。--typescripフラグをつけると、TypeScriptに対応したプロジェクトを作成してくれます。

$ npx create-react-app my-app --typescript

Bugsnagの導入

Reactに対応したBugsnagのライブラリがあるのでインストールします。

$ yarn add @bugsnag/js @bugsnag/plugin-react

インストール後、index.tsxにライブラリを読み込みます。your_keyには、Bugsnagで取得したAPIキーを入れます。これで準備が完了です。実際にエラートラッキングを送ってみましょう。
inex.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

import bugsnag from '@bugsnag/js';
import bugsnagReact from '@bugsnag/plugin-react';

const bugsnagClient = bugsnag('your_key);
bugsnagClient.use(bugsnagReact, React);

const ErrorBoundary = bugsnagClient.getPlugin('react');

ReactDOM.render(
  <ErrorBoundary>
    <App />
  </ErrorBoundary>,
  document.getElementById('root'),
);

serviceWorker.unregister();

エラートラッキングの送信

意図的にアプリケーションをクラッシュさせるコンポーネントを作成します。
App.tsx

import React, {useState} from 'react';

const App: React.FC = () => {
  const [count, setCount] = useState(0);

  const handleAdd = () => {
    setCount(count + 1);
  };

  if (count === 3) {
    throw new Error('クラッシュしました!');
  }

  return (
    <div className="App">
      <h1>カウント - {count}</h1>
      <button onClick={handleAdd}>+</button>
    </div>
  );
};

export default App;

これで、アプリケーションを立ち上げてみましょう。

$ yarn start

f:id:kamimura-dev:20200103154805p:plain

プラスボタンを3回押すと、クラッシュさせることができます。

f:id:kamimura-dev:20200103154939p:plain

そして、Bugsnagのダッシュボードを見てください。そこでエラートラッキングできてることが確認できます。

f:id:kamimura-dev:20200103155056p:plain

ErrorBoundaryにエラー画面を追加

react-bugsnagのライブラリをみたところ、ErrorBoundaryのFallbackComponentコンポーネントを渡すことで、アプリケーションがクラッシュする前にエラー画面を出すことができます。

ErrorBoundary は 子コンポーネントツリーで発生したエラーをハンドリングする ための React コンポーネントとして、公式ドキュメントでも紹介されています。

ja.reactjs.org

index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

import bugsnag from '@bugsnag/js';
import bugsnagReact from '@bugsnag/plugin-react';

const bugsnagClient = bugsnag('your_key');
bugsnagClient.use(bugsnagReact, React);

const ErrorBoundary = bugsnagClient.getPlugin('react');
//追加
const ErrorFallbackComponent = () => <div>エラーが発生しました!</div>;

const beforeSend = (report: string) => {
  console.log('about to send this report', {report});
};

ReactDOM.render(
  //追加
  <ErrorBoundary
    FallbackComponent={ErrorFallbackComponent}
    beforeSend={beforeSend}>
    <App />
  </ErrorBoundary>,
  document.getElementById('root'),
);

最後に

Bugsnagを導入して、簡単なエラートラッキングを送ってみました。Bugsnagを利用する場面は多数ありそうですね。個人的にフロントエンドの障害設計は難しいと感じます。今後もいろいろ試してみて、良さそうな物があったら紹介していきます。