*本記事は STORES Advent Calendar 2023 5日目の記事です
こんにちは。リテール開発本部に所属しています、tommy です。
STORES では、エラー監視ツールとして Sentry を導入して、日々開発をしています。
今回は、直近外部サービスのAPIを利用する開発をしていた際に、Sentryのエラー整理に fingerprint を活用した話について紹介いたします。
また、 STORES のプロダクトでのSentryの活用についてはこちらのブログにまとめてくれているので合わせてぜひご覧になってください。
背景
私が所属するリテール開発本部でのプロダクト開発において、利用している外部サービスをあたらしいサービスに切り替える開発をしていました。
その外部サービスのAPIレスポンスは、エラーの場合、body にエラーコードとエラーメッセージを含む構造です。
{ "result": false, "errors": [ { "code": 1000, "message": "error message" } ] }
この開発では、既存APIと並行して、新規APIへリクエストを行い、正常に切り替えられるかどうかを確かめながら実装していました。
ここで、新規APIリクエストの結果がエラーだった際には、どのエンドポイントだったとしても共通のエラーハンドリングにより、Sentry にエラーとしてイベントを飛ばしていました。
しかしこの形だと「呼び出し箇所の種類 × 外部サービスへの実行APIの種類 × エラーの種類」 という組み合わせで、それぞれ違うissueとして大量に作成されてしまってしました。
Sentry と Slack を連携し、普段運用しているため、新規 issueのたびに通知がきてしまい、大事な通知を見落としてしまいかねないという影響もありました。
また、サービスの導入というところでどのようなエラーの種類が発生しうるのか、というところも合わせて把握したかったのですが、それもしづらい形になってしまっていました。
Sentryでは、エラーイベントを issue という単位で管理し、各 issue は fingerprint という独自の情報を持っています。 fingerprint は、デフォルトではスタックトレース、例外情報、エラーメッセージなどを基に生成されます。
実際にSentryの各 issue ページの一番下に fingerprint の情報がのっています。
fingerprint を活用した issue のグルーピング
Sentryでは、前述した fingerprintを変更拡張することができ、用途にあわせてグルーピングさせることができます。
ドキュメント上では4種類の方法が紹介されています。
-
- 手動で特定の issue を選択し、マージしていく方法
-
- 送られてくるイベントに対して、特定の条件と条件に当てはまる場合に設定したい fingerprint を 指定する方法
-
- 送られてくるイベントに対して、fingerprint を構成する スタックトレースの内容を、条件をしていして変更する方法
-
- SDK経由でイベント送信時に fingerprint を指定する方法
実際の設定
今回は、外部サービスへのAPIレスポンスのステータスコードやエラーコードごとに issue をわけたかったので、 SDK Fingerprinting で対応しました。
sentry-ruby を導入しているので、Ruby のSDKページに載っているコード例を参考にのせますが、 設定は簡単で、このように fingerprint という key を追加し、値に配列で fingerprint としていれたい情報を渡すだけです。
def do_something(action_name) # some code rescue => exception Sentry.capture_exception(exception, fingerprint: [__method__, action_name]) end
エラーの種類の単位でわけたかったので、エラーハンドリングの共通処理部分で以下のように fingerprint を設定してイベントを飛ばすように変更しました。
# 各エンドポイントへのリクエストでエラーが発生した際に共通で呼び出す def handle_error(error, action, status_code, error_code) Sentry.capture_message( "API Request Error. status code: #{status_code}, error code: #{error_code}", # fingerprint の引数に指定したい値を配列で渡す fingerprint: Rails.env.production? ? ['api request error', action, error.class, error.status_code, error.error_code] : nil, ) end
通常では Sentry側の自動グルーピングで環境が別の場合、issueは分割されますが、fingerprint を設定してしまうと、別環境でも同一のissueと見なされてしまうため指定しています。
fingerprint を nil に指定した場合は、 デフォルトの fingerprint 設定が適用されて issue が作られます。
結果
これを設定したことにより、利用APIの種類ごと、エラーの種類ごと、に分類でき、Sentry上での issue を整理できました。
issue で表示されている fingerprint は以下のようになっていて、custom-fingerprint として指定した形に上書きできていることが確認できます。
issue がまとまったことにより、issue単位で設定ができる特定条件まで通知をしないなどの Archive 設定を、分割したエラーの種類の単位で設定ができるようになり、Slackに通知がきすぎてしまう問題も解決できました。
また、詳細は省きますが、Sentry には tag という issue に対する補足情報がついています。
今回エラーの種類ごとにissueを設定しましたが、tag を活用することで、transaction や url と言った情報から呼び出し箇所の内訳もみることができます。
まとめ
fingerprint を活用した、エラー整理の話でした。
途中取り上げた他のグルーピング手法もいろいろあるので、ぜひ調べて活用してみてください。
おわりに
本記事は STORES Advent Calendar 2023 5日目の記事でした!
次回は soh さんです。
soh さんは2日目にも Advent Calendar の記事を書いているので、合わせてぜひ読んでみてください!