Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails以外の開発一般

Better Stimulusガイド 03: エラーハンドリング(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

🔗 グローバルなエラーハンドラ

こんなときに使いたい

Stimulusに関連するエラー(connectエラー、targetsにアクセスできないなど)やアプリケーションエラーをコントローラ内でキャッチして、SentryHoneybadgerなどのエラートラッキングサービスに送信したい場合。

ソリューション

最初に、自分のStimulusコントローラが継承するグローバルなApplicationControllerを作成します。

このApplicationControllerの中でhandleError関数を定義します。この関数は、現在のユーザーidで小さなコンテキストオブジェクトを作成します。このコンテキストオブジェクトには、環境やサブスクリプションステータスなどデバッグに役立つあらゆるコンテキスト情報を渡せます。

Stimulusには、ドキュメントにほとんど書かれていないエラーハンドラが含まれています(末尾のリンクを参照)。デフォルトでは、このエラーハンドラはすべてのStimulus内部エラーをキャッチし、整形してからconsole.logに出力します。

定義したhandleError関数内でこのapplication.handleErrorにカスタムコンテキストを渡して呼び出すことで、エラーの管理や報告を行う単一の関数を利用できるようになります。

Good

// app/javascript/controllers/application_controller.js
import { Controller } from "stimulus";

export default class extends ApplicationController {
  handleError = (error) => {
    const context = {
      controller: this.identifier,
      user_id: this.userId,
    };
    this.application.handleError(
      error,
      `Error in controller: ${this.identifier}`,
      context
    );
  };

  get userId() {
    return this.metaValue("user_id");
  }
}

これで、以下のように自分のコントローラでエラーをキャッチし、 this.handleErrorに渡してエラーを報告できるようになります。

// app/javascript/controllers/some_controller.js

export default class extends ApplicationController {
  someFunc() {
    try {
      // ...
    } catch (err) {
      this.handleError(err);
    }
  }
}

通知サービスを追加する

以下はStimulusのエラーをSentryに送信する設定例です。

Good

// app/javascript/packs/application.js
import { Application } from "stimulus";
import { definitionsFromContext } from "stimulus/webpack-helpers";

const application = Application.start();
const context = require.context("./controllers", true, /\.js$/);
application.load(definitionsFromContext(context));

// デフォルトのハンドラをメモ化
const defaultErrorHandler = application.handleError.bind(application);

// Sentryをエラーログに設定してデフォルトハンドラをprependする
const sentryErrorHandler = (error, message, detail = {}) => {
  defaultErrorHandler(error, message, detail);
  Sentry.captureException(error, { message, ...detail });
};

// 新たに組み立てたハンドラでデフォルトハンドラをオーバーライド
application.handleError = sentryErrorHandler;

これで、このハンドラはグローバルなエラーをSentryに送信します。さらに上の例では、アプリケーションコード内のtry/catchブロックでこの関数を使ってエラーをキャッチする方法も示されています。

そうする理由

すべての理論的根拠は、単一のエラーハンドラでStimulusコントローラ内のすべてのエラーをハンドリングできるようにするためです。Stimulusのエラーもアプリケーションのエラーも、すべて同じパスを通ります。このエラーハンドラを設置するだけで、エラーメッセージにコンテキストを追加して、SentryHoneybadgerなどに手軽に送信できます。

参考情報

関連記事

Better Stimulusガイド:アーキテクチャ(1)アプリケーションコントローラ(翻訳)

Better Stimulusガイド:アーキテクチャ2: コントローラはコンフィグ可能にしよう(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。