【Nuxt3】Sentryを使ってフロントエンドのエラー監視を強化しよう!
お知らせ
5月24日にSentryにまつわるウェビナーを開催いたしました。
レポート記事を公開していますので、ぜひご覧ください。
【Sentry】Webフロントエンドの新定番!?Sentryが攻略するエラーの迷宮 part1勉強会レポート
はじめに
こんにちは、フロントエンドを担当しております森です!
今回、新規モバイルアプリ開発のフロント業務を担当する際にSentryを導入し、改めて設定・運用について考えてみたので、それについての共有記事になります。
少しでもテストやエラー管理に悩まれている方の補助となれば嬉しいです!
こんな体験ありませんか…?
- アプリリリース間近のテスター確認。エラーの共有に時間が割かれてしまう
- リリース後。ユーザーがエラーに遭遇しているようだが、発生条件が分からない
- アプリ全体のパフォーマンスを改善したい
- 遭遇したエラーの詳細を保存して、管理・解決したい
これらの問題、Sentryで解決できるかもしれません!
Sentryとは?
Sentryとはエラーの監視ツールです。ブラウザ上でエラー発生時のスタックトレースや、リクエストデータなどを確認することができます。
バックエンド・フロントエンド問わずあらゆるプラットフォームでのエラー監視に対応しています。
サーバー側のエラー検知はやっていても、フロント側ではやってないという人も多いかと思います
Sentry を使えば、たとえば以下のようなことが分かります
- どの環境で発生したどのようなエラーか?
- アプリのパフォーマンスを下げている機能は?
- コード上のどの部分で発生したエラーか?(ソースマップ設定時)
- どのような操作をすればエラーが発生するのか?(Session Replay設定時)
- エラーの種類・対応が必要なエラーか?(Alert設定時)
現状、エラー監視を手動で行っているプロジェクトなら、導入を検討してみてはいかがでしょうか?
導入
設定の一例
導入方法は公式ページで丁寧な説明があるため、ここでは省きます。
Sentryを導入した最近の一例として、Webviewを使ってのモバイルアプリ開発(Nuxt3 × TypeScript × Vite)の事例を挙げます。
ソニックムーブではTeamsプランで運用しています。Slack連携など一部の機能は無料のDeveloperプランでは使えないことに注意しましょう。
以下、初期化時の設定になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
/** plugins/sentry.client.ts */ import * as Sentry from '@sentry/vue'; export default defineNuxtPlugin((nuxtApp) => { const { vueApp } = nuxtApp; const config = useRuntimeConfig(); const router = useRouter(); const appEnv = config.public.appEnv; const appUrl = config.public.appUrl; const sentryDsn = config.public.sentryDsn; Sentry.init({ app: [vueApp], dsn: sentryDsn, environment: appEnv, integrations: [ new Sentry.BrowserTracing({ tracingOrigins: ['localhost', appUrl], routingInstrumentation: Sentry.vueRouterInstrumentation(router), }), // Session Replay の設定 new Sentry.Replay({ maskAllText: true, blockAllMedia: true, }), ], // 開発中にlocalhostからエラーを送信したくない enabled: appEnv !== 'local', // サンプリングレート設定 // NOTE: Transaction上限を確認しながら設定する tracesSampleRate: appEnv === 'prod' ? 0.05 : 1.0, // エラーの有無に関わらずユーザーのセッション全体に渡って計測する比率(Session Replay) replaysSessionSampleRate: appEnv === 'prod' ? 0.01 : 1.0, // エラーが発生する1分前からセッションの終了までを計測する比率(Session Replay) replaysOnErrorSampleRate: 1.0, ignoreErrors: [ 'Network Error', 'NotSupportedError' ], beforeSend(event, hint) { // エラーを明示的にグルーピング if (event.message === 'Failed to fetch') { event.fingerprint = ['failed-to-fetch']; } if (event.exception) { console.error( `[Exeption handled by Sentry]: (${hint.originalException}, , { event, hint })`, { event, hint }, ); } return event; }, }); |
environment
今回のアプリでは環境ごとに prod, stg, dev, local のいずれかの文字列を渡しています。
integrations
Sentryで用意されているインテグレーションを設定できます。追加ライブラリのようなものという理解で問題ないと思われます。
おおよそデフォルト設定でも十分に便利ですが、ここではBrowserTracing(自動パフォーマンス監視)とSessionReplay(エラー前後のユーザーの行動を動画で再現)を有効化しました。
他にもたくさんあるので、ざっくり把握しておくと便利そうです(https://sentry.io/integrations/)
tracesSampleRate
アプリがリリースされると、膨大なユーザーが使うことが予想されます。すべてのエラーを拾っていてはすぐに月の上限を超えてしまいます。
サンプリングレートを適切に設定して、エラーを拾いすぎないようにします。逆に開発時はすべてのエラーを検知して欲しい場合が多いので、1.0に近い値を設定することがおすすめです。
replaysOnErrorSampleRate / replaysSessionSampleRate
SessionReplayのサンプリングレート。これも適した値を設定します。
enabled
Sentryへエラーを送信する環境(またはURL)を設定できます。開発中、ローカルからのエラーは基本キャッチしなくても良いはずなので、弾いてしまいましょう。
ignoreErrors
無視したいエラーを配列で設定します。ここに設定しておくと、Transactionを消費しないようなので、恒久的に対応しなくてもよいエラーは積極的に追加するようにすると料金を抑えられます。
beforeSend
エラー送信を行う前に実行する処理を定義できます。ここでは異なるエラーとして認識されてしまうエラーの明示的なグルーピングと、log出力をおこなっています。
ビルド時にソースマップをSentryへ送信する設定もしています。
ビルド時にminifyされるアプリは、エラーが発生してもコードのどの部分でエラーが発生したのか人間には分かりません。そのため、ビルド時にソースマップをSentryに登録する設定が必要です。
Viteを使っている環境なら、以下のように簡単に設定できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/** nuxt.config.ts */ import { sentryVitePlugin } from '@sentry/vite-plugin'; export default defineNuxtConfig({ vite: { // Sentryソースマップ設定 https://docs.sentry.io/platforms/javascript/guides/vue/sourcemaps/ build: { sourcemap: true }, plugins: [ sentryVitePlugin({ org: 'your-project-organization', project: 'your-project-name', authToken: process.env.NUXT_PUBLIC_SENTRY_AUTH_TOKEN, sourcemaps: { // ビルド出力先のディレクトリを指定 assets: ['./.output/**'], ignore: ['./node_modules/**'], }, }), ], }, )} |
sourcemap.assets
ビルド成果物が出力されるディレクトリを指定します(通常は設定の必要はありません)
今回の運用ルールと得られた知見
今回は単独での運用だったので運用ルールは最小限です。
必ず開発者が定期的に確認してエラーを仕分けること
サンプリングレートはその月のTransactionを越えないように適宜調整すること
すべてのIssueに対応するとタスクが増える一方なので、アラートのフィルタリングをする
・今回ディレクターへの共有を簡単にするため、Slack通知(※Teamsプランのみ)を利用
・通知条件は「本番環境&対応ブラウザ&週に10件以上報告されるエラーのみ」とした
・開発者用と他の職能間に共有する用の通知Slackチャンネルは分けた方がよいかもしれない(前者は縛りをゆるく、後者はよりクリティカルなエラーだけを通知する)
発生した課題はSentryで管理すること
・Issueの詳細のActivityタブで各Issueにコメントすることができる
・対応不要とした場合も必ずコメントを残すこと
感じたメリット
テスト時に、テスターに現象を共有してもらう時間が節約できる
通常見逃してしまいそうなエラーも検知できる
・滅多に発生しないエラーや特定条件下のみで発生するエラーも検知可能
・リリース後、ユーザーのエラー報告を待つ必要がなく修正に当たることができる
エラー原因が追いやすい
・どの部分のコードでエラーが起きたか簡単に分かる
・ユーザーの操作を見られるSessionReplayが優秀すぎる…!
パフォーマンスに関する多くのデータが取れる
・何かしら活用できそう ・パフォーマンスに影響を与えている機能が一目瞭然
エラー原因が追いやすい
・Slackなど他のツールとの連携が簡単
・他の職能間で共有が簡単
これからの課題
今回はエンジニア単独での運用だったため、簡単な設定でもどうにか運用できていました。複数人での長期運用を前提とすると、よりよい方法が見つかるかもしれないので、知見をアップデートしていきたいと思っています。
パフォーマンスに関しては、分析しがいのありそうなデータが取れてはいるものの、現状あまり活用できていないため、これから改善と活用法を模索していきたいと思います。
おわりに
今回、本格的にSentryを導入してみて、これからはフロントでもエラー監視が欠かせない機能になることを確信しました。デバッグやフィードバック修正においても対応時間をかなり短縮できたと思います。開発者だけでなく、プロダクトに関わるすべての人にとってメリットがあるのではないでしょうか?
この記事が少しでも導入の後押しとなれば幸いです!お読みいただきありがとうございました。