🉐

Sentryのセッションリプレイ料金を90%以上削減した話

2024/06/10に公開

はじめに

現在のプロジェクトでは、主にフロントエンドの開発に従事しています。このプロジェクトでは、Sentryを使用してエラートラッキングを行なっています。その中でもセッションリプレイはエラー前後のユーザーの行動を再現することができ、エラーの解析に非常に有用です。しかし、プランによっては無料枠があるものの、無料枠からはみ出した分は基本料金とは別の支払いとなります。以下は執筆時点(2024/06/10)でのセッションリプレイの料金体系です。

プラン名 支払い方式 無料枠 データ保持期間 1セッションリプレイあたりの料金
Team 月払い 500リプレイ 90日 約$0.0029 ~ $0.0021
Team 年払い 500リプレイ 90日 約$0.0026 ~ $0.0019
Business 月払い 500リプレイ 90日 約$0.0029 ~ $0.0021
Business 年払い 500リプレイ 90日 約$0.0026 ~ $0.0019

TeamとBusinessはプランによって1セッションリプレイあたりの料金に変わりはないものの、支払い方式や総セッションリプレイ数によって変動する仕組みとなっています。

今回は、セッションリプレイのコストを大幅に抑えた設定や運用方法の紹介をしたいと思います。

削減しようとした背景

私が携わっているプロジェクトが他のプロジェクトより100倍セッションリプレイが送信されている報告を受け調査してみると、期待通りの使用量でないことがわかりました。月々のコストも嵩んでいることから早急に設定や運用を見直すことにしました。

原因

結論から言うと、デバッグ目的でSentryに送信していたアプリケーションログと一緒に意図せずセッションリプレイが送られていたことが原因でした。
過剰に送られている原因としては、上記の送信していたエラーは(業務影響はないが)ユーザー側で高頻度で起こるものであったことと、エラーの際にセッションリプレイのサンプル率が100%になっていたことでした。
あまり数はないんですが、環境ごとにサンプル率などを調整する設定を怠っていたことも原因として挙げられます。

あと直接的な原因ではないんですが、Sentryの導入チュートリアルにはreplaysSessionSampleRatereplaysOnErrorSampleRateがあらかじめ数値が入力されているので、コピペして使っている方は気をつけたほうが良いかもしれません。

対策

上記の原因からセッションリプレイを送信するルールを定めて、SDK側に設定することにしました。ルールは以下です。

  1. 開発環境ではセッションリプレイを送らない
  2. replaysSessionSampleRateはどの環境でも0%
  3. error.leveldebugの際にはセッションリプレイは送らない

ルール1の理由は、開発環境は主に開発者が触るのでセッションリプレイを利用してユーザーの操作を再現する必要がないことから開発環境ではセッションリプレイは必要ないと判断しました。

ルール2のreplaysSessionSampleRateというのは、エラーの有無に関わらずセッションリプレイを送信する比率です。理由としては、私のプロジェクトではエラー事象の再現以外にセッションリプレイを使うユースケースがなかったのでreplaysSessionSampleRateは0%に設定することにしました。

ルール3理由は、デバッグ目的でSentryに送信しているエラーは高頻度で起こるかつ、現状セッションリプレイから得られる情報が特に必要なかったので送らない、としました。

上記のルールをSentryのSDK側に設定すると以下のようなコードになります(イメージです)

import { init, BrowserTracing, Replay } from '@sentry/react'
import { BUILD_ENV, RELEASE_ID, SENTRY_DSN } from '@/constants/env'

const isSentryEnabled = SENTRY_DSN !== undefined || BUILD_ENV !== 'local'

export const initializeSentry = () =>
  isSentryEnabled &&
  init({
    dsn: SENTRY_DSN,
    integrations: [
      new BrowserTracing(),
      new Replay({
        beforeErrorSampling(event) {
          return event.level !== 'debug' && BUILD_ENV !== 'development'
        },
      }),
    ],
    environment: BUILD_ENV,
    tracesSampleRate: 0.1,
    replaysSessionSampleRate: 0,
    replaysOnErrorSampleRate: 1.0,
  })

ポイントは、beforeErrorSamplingというメソッドです。こちらは@sentry/react@7.78.0以上から実装された機能です。このメソッド内では、エラーが起きた時にセッションリプレイを送るか送らないのロジックを実装することができます。

Sentry.withScope((scope) => {
    scope.setLevel("debug")
    scope.setExtras(data)
    Sentry.captureException(error)
  })

上記のように、エラーを送信する実装の箇所で、setLeveldebugを渡すと、beforeErrorSamplingでフィルターされる仕組みです。

結果

具体的な金額や数は伏せますが、元々送り過ぎていたこともありその後のコストと比べた結果、90%以上の削減に成功しました。

まとめ

いかがでしたでしょうか?効率的にセッションリプレイを使用しつつコストを大幅に削減することができました!
どういった条件では送らないなどチームで方針を決める必要はあるものの、実装としては軽微なのでセッションリプレイのコストの削減に取り組んでみるのはいかがでしょうか!

株式会社BuySell Technologies

Discussion