クライアントでのエラー監視要員としてSentryを導入した話

どうもはじめまして、トラストバンクでフロントエンドエンジニアをしている田口です。 早速ですが少し前にそのふるさとチョイスにSentryを導入したので、今回はそれについて書こうと思います。

解決したかったこと

ふるさとチョイスはありがたいことにとても多くのユーザーがいます。そしてそれに比例するように、クライアント環境もたくさんあります。
特にふるさとチョイス、というより弊社のサービスはその性質上、他社さんのサービスと比べて恐らくですが、特殊な環境であったり、IEなどの古めな環境で使われることが多いです。
それゆえ、ユーザーから不具合に関する問い合わせを受けても、こちらで持っている環境ではほとんど再現せず、原因調査と改善に至らないこともあります。
まぁIEゆえに発生するような不具合は再現しやすいほうなのですが……。

このような環境依存の不具合に関する問い合わせは、サービス全体としては特殊な例ですが、それが発生したユーザーにとってはその不具合が全てですから、解決しないとなるとサービスから離れてしまい、ユーザーにとっても我々にとっても不幸な結果になります。
こうした不幸を少しでも減らすために、原因調査の手助けとしてSentryを導入することとしました。

Sentryへの登録と仮導入

Sentryについての説明は省略しますが、まずは登録をします。
登録は英語ですが、特に複雑なことはありません。必要項目を入力して進めていくと、すぐにStart upを開始できるようになります。
導入に使用する言語が選択可能で、JSだけでなくJSフレームワークであるReactやVue、Node.js、もしくは別の言語を選択することもできます。

f:id:gatag:20220225190915p:plain
クライアントサイドだけでなくサーバーサイドも

Qiitaにもさらっと書いたのですが、ふるさとチョイスはJSフレームワークをまだ導入していないので、普通のJSを選択しました。
言語を選択すると、あとはもうチュートリアルの手順に従ってコードを仕込むだけです。めちゃ簡単……

仮導入で気になったこと

仮導入していて2つほど気になったことがありました。

dsn って公開していいの?

Sentry SDKのコードを実装するにあたり、dsnがベタ書きなのが気になりました。dsnというのはお察しの通り(?)、Data Source Nameの略語です。
Sentryのドキュメントにもdsnの説明がありますが、公開された状態でも問題無いと書かれています*1ので、結局特に何もせずベタ書きにしています。

コード量が増えた

ふるさとチョイスはES2015↑のコードをWebpack + Babelに噛ませてビルドしています。
で、実際にSentry SDKを実装したところ、ビルドされたJSファイルがまあまあ膨れ上がりました。
これに関してはパフォーマンスを確認した上で許容としていますが、個人的にはなんとかしたいと思っています。なんとかならんのか

チューニング

チュートリアルの内容だけでもエラーを検知してSentry画面上で確認することはできたのですが、実際に使っていくうえではチューニングの必要性が見えてきました。

whiteListUrlsの設定

whiteListUlrsは監視するファイルを正規表現で範囲を絞り込むための設定なのですが、最初はこれをドメインレベルまでの設定にしていました。
これだけでもサードパーティのJS(マーケティングツール関連など)にて発生したエラーを監視してSentryに送るようなことは無くなりました。しかし、送られてくるエラーのほとんどが内容的にサードパーティのものであり、こちらで実装したものではありませんでした。

f:id:gatag:20220228105217p:plain
GTMのJSでエラーが起きているのをキャッチしてしまった
なんでかな〜と思っていたところ、辿っているうちに発生箇所がdocumentの中だということに気づき、document内に書かれてしまうとドメインレベルでのホワイトリスト設定は通過してしまうことが分かりました。

document内に書いてあるJSが一切無いというわけではないのですが、それらのほぼ全てがタグマネージャやアナリティクスに関するものだったため、ホワイトリストとしてはJSのディレクトリに絞りました。

tracesSampleRateの設定

これはSentryのドキュメントをちゃんと見ていなかっただけなのですが、普通にユーザーが来訪する本番環境に適用するには、tracesSampleRateをチュートリアルで書かれている1.0から下げるべきだったのです。
それに気付かずに本番環境に導入したことで、仮導入したページは一部だったにも関わらずかなりの勢いでトランザクションが消費されてしまいました。

f:id:gatag:20220228105713p:plain
来訪の少ない一部のページだけに入れたはずなのに42%も食われた
本格導入するにあたっては1.0のままではすぐにトランザクションを使い切ってしまうので、これを下げます。

そもそもSentryのトランザクションとはどういう時に使われるのか、調べてみたところどうやらSentryのトランザクションはエラー監視ではなくパフォーマンス監視に使用されているようです。*2
ふるさとチョイスはNew Relicも使用していますので、パフォーマンス監視はSentryではそれほど必要ではないはず……ということで思い切って0.001にまで下げました。

テスト環境やローカル環境時の動作の実装

これに関しては仮導入の段階で実装していました。
テスト環境やローカル環境で発生したエラーに関しては、本番環境のものとは分けて管理するか、そもそも監視しないという選択肢になると思います。
まずローカル環境に関しては全く監視しなくて良いので除外できるようにしたい……
テスト環境に関しては監視しつつも本番環境とは分けて管理したいため、何かしらの識別子が欲しいところ……
と思っていたところenvironmentというそのまんまのパラメータが用意されていました。
ということでドメインに基づいて簡単な制御を追加しておきました。

const getSentryEnv = () => {
  const domain = document.domain;
  if (/* ローカルだったら */) {
    return 'local';
  } else if (/* 本番だったら */) {
    return 'production';
  } else {
    return 'test';
  }
};
const sentryEnv = getSentryEnv();
if (sentryEnv !== 'local') {
  Sentry.init({
    // dsn等は省略
    environment: sentryEnv,
  });
}

これからやっていきたいこと

現段階ではまだ軽くチューニングをしただけですので、本格的に運用するためにはやるべきことがいくつかあります。

エラーのトリアージ方針決め

全てのエラーに全力対応するぜ!みたいな気合いや人員、時間があればいいのですが、現実そうはいかないので、エラーによっては対応しなかったり、逆に他のエラーを差し置いてでも対応する必要があるものもあると思います。

現状ではまだ一部ページだけでSentryの監視をスタートしているのですが、それでもすでに1日5件のペースでIssueが増えていますので、サービス全体を監視し始めるより前にトリアージ方針をある程度は決めなければなりません。
サンプルとなるデータも集まり始めているので、それを基に検討していきたいと思います。

フィルタリング

トリアージ方針とほとんど同じなのですが、Sentryの表示自体にもフィルタリングをかけると見やすくなるだろうなと思っています。

また、Unresolved、For Reviewなど、エラーごとにステータスをつけるというフィルタリングもありますので、ステータスの変更フローなどの検討もこれに含めて考えています。
SentryではReleaseという管理項目(?)もあり、SDKでパラメータを送ったりすることで、どのリリース後に起きたエラーかをタグ付けすることができます。これもまたエラーのフィルタリングで使えそうです。 ReleaseはGithub Actionsでの連携が基本になりそうなので、少しハードルは高そうですが、使用することでのメリットが大きそうなので検討していきたいところです。

Slackとの連携を直す

チャンネルを作成してSlackとSentryの連携まではできたものの、今のところ稀にメッセージが入るだけで、新しいエラーがSentryに追加されてもそれがSlackで通知されないという状態になってしまっています。 恐らく厳し目なフィルタリング設定をしてしまっていると思うので、連携設定の見直しをはかろうと思っています。

まとめ

クライアントで発生したエラーを簡単に取得できるようになった一方、まだまだ本格的に運用するには設定等の見直しが必要な状態ですので、引き続きSentryの面倒を見ていこうと思います。

トラストバンクではSentryを導入して運用してきたような、クライアントで発生するエラーにも強いエンジニアを募集しております! www.wantedly.com

それでは〜ノシ