SentryのSession Replayを導入してみて

## はじめに
Sentry利用していますか？
社内ではフロントエンドのエラーの監視のためにSentryを導入しています。

ある日、Sentryを開いて新たなエラーが計測されているか確認していたところ
> Your organization has access to Session Replay for free until the end of August,
![スクリーンショット 2023-07-13 18.13.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591069/24747280-6b70-7446-0142-4bb61e3840c2.png)


Session Replayというサービスを8月末まで無料にしてあげるから使ってみないかい？と画面上部に表示されました。

ダッシュボード上にReplaysという項目がありますが、表示されるまではその機能を知りませんでした。無料という言葉に興味が惹かれてので調べてみると、
>Session Replay helps you get to the root cause of an error or latency issue faster by providing you with a video-like reproduction of what was happening in the user's browser before, during, and after the issue. You can rewind and replay your application's DOM state and see key user interactions, like mouse clicks, scrolls, network requests, and console entries, in a single combined UI inspired by your browser's DevTools.

https://docs.sentry.io/platforms/javascript/session-replay/

とあり、エラーが発生する前後でユーザーの行動を視覚的に再現してくれるツールということがわかりました。具体的には、WebアプリのDOMのスナップショットから作成された一連の操作を動画として再現したものを生成してくれます。

このような性質をもつSentry ReplayはSentryが監視したエラーを記したIssueでは調査しきれなかった問題の再現や解決の助け舟になるだろうと考えお試しで取り入れました。

この記事はそんなSession Replayについて導入から感想までを書き記します

## Session Replayの導入
Sentry Replayの導入はReact×Vite環境で行いました。開発環境によってそれぞれ利用するライブラリに差分がありますが、ベースは`@sentry/browser`の機能なので同じように取り入れられると思います。
この記事では`@sentry/react`ライブラリを利用しますが、[同等のライブラリ](https://github.com/getsentry/sentry-javascript#supported-platforms)であれば導入可能です。専用のライブラリは必要ありません。
なお、ライブラリのバージョンは7.27.0以上である必要があり、IEやNode12以前の環境には対応していません。

Sentry Replayを取り入れるまでのSentryの設定は以下のようになっているものとします。
```ts
import * as React from '@sentry/react';

Sentry.init({
  dsn: SENTRY_DSN,
  integrations: [new Sentry.BrowserTracing()],
  tracesSampleRate: 0.1,
});
```
Session Replayを有効にするためには`itegrations`の追加と計測比率を設定します。

```ts
import * as React from '@sentry/react';

Sentry.init({
  dsn: SENTRY_DSN,
  integrations: [new Sentry.BrowserTracing(), new Sentry.Replay()],
  tracesSampleRate: 0.1,
  replaysSessionSampleRate: 0.01,
  replaysOnErrorSampleRate: 1,
});
```
`integrations`に`new Sentry.Replay()`を追加することでSession Replayの有効にします。

`replaysSessionSampleRate`はエラーの有無に関わらずユーザーのセッション全体に渡って計測する比率です。セッションはユーザーが非アクティブな状態を15分続けるか、60分経過した時点で終了します。
エラー以外で計測する必要ない場合は0にするのが良いです。動作検証の段階では高く設定して本番では低く設定することがおすすめされています。

`replaysOnErrorSampleRate`はエラーが発生する1分前からセッションの終了までを計測する比率です。エラーが頻発する環境では計測頻度と料金で適切な値を見積もる必要がありますが、エラーが発生しても取得できずに原因を探れないと困るので通常は1に設定するのが良いと考えています。

Session Replayを動かすのに必要最低限の設定はこれで完了です。

## 再現結果のプライバシーについて
デフォルトでは実際の画面から個人情報をマスクした状態で操作している様子を動画で確認できます。
![masking.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591069/c8fedd94-be92-b227-1b94-37850493f605.png)
画像はhttps://docs.sentry.io/platforms/javascript/guides/nextjs/session-replay/privacy/#masking から引用

マスクされるものはすべてテキストコンテンツとすべてのメディア要素 ( img、svg、videoなど)です。 
Sentryの設定で`maskAllText`を`false`に設定してマスクを解除できます。また、html要素の`class`に対して`sentry-mask`、`sentry-block`を付与することでマスクの有無を調整可能です。

## パフォーマンス
最初に説明した通り、Session ReplayはWebアプリのDOMのスナップショットから作成された一連の操作を動画として再現したものを生成します。そのため、DOMの監視とそれをSentryに送信する必要があり、パフォーマンスへの悪影響が懸念されます。
このようなパフォーマンスの低下に対してSentryは様々な工夫を凝らして悪影響を最小限にしています。

- Session Replayを動かすファイルの軽量化
- 最初のDOMツリーのスナップショットを送信後は差分のみ送信
- Web Worker内でgzip圧縮したデータを送信
- 画像やビデオなどの他の静的アセットはダウンロードして送信せずに元のサーバーから直接取得
- [PoP](https://blog.sentry.io/sentry-points-of-presence-how-we-built-a-distributed-ingestion/)によるネットワークオーバヘッドの軽減
- DOMの変化が大きいときはSession Replayを無効化することによって通常以上のパフォーマンスの低下を阻止

このような最適化を行っていることもあり、ドキュメントではSession Replayの導入によるユーザー体験への影響はほとんどのアプリで起きないと書かれています。
> For most web applications, the performance overhead of our client SDK will be imperceptible to end-users.

実際にSentryへDOMのスナップショットを送信する様子を確認してもせいぜい数十バイト程度で、アプリの使用感も主観ですが採用前から変化を全く感じませんでした。
そのため公式に書かれており通り、余程複雑にDOMを操作するアプリケーションでもない限りほとんど考慮する必要はないのではと考えています。
アプリケーションのパフォーマンスの変異を詳細に測定したい場合は、[Sentryの公開している計測方法](https://sentry.engineering/blog/measuring-session-replay-overhead)を元に計測できます。

## 料金体系
料金体系は[公式ドキュメント](https://docs.sentry.io/product/accounts/pricing/#replays-pricing)によると以下のように設定されています。
| 総リプレイ数	| Prepaid Buckets | Team/Business Prepaid |	Team/Business オンデマンド |
| --- | --- | --- | --- |
| >10k-25k | 15k | $0.002850 | $0.003705 |
| >25k-100k	| 25k | $0.002850 | $0.003705 |
| >100k-1M | 100k | $0.002565 | $0.000195 |

## 導入した感想
### エラーの調査と改修
エラーが発生した際にコードを元に動作を再現して確認することが多いですが、Session Replayを確認するだけで動作の確認が可能なので調査工数を削減できました。

さらに、エラーが発生した場所だけではその要因を特定できないケースがあります。そのようなケースでもSession Replayがあることで前後の操作を確認してどのようにそれがどのように発生したかを確認できるようになりました。これにより正確で迅速な改修が可能になりました。

Session Replayを導入するとエラーに関する調査工数の削減と改修の正確性と速度が向上するので、開発体験もユーザーへのフィードバック速度も上がりました。

### 思わぬ収穫について
`replaysSessionSampleRate`を0にしていなかったので、普段ユーザーがどのように操作していて、どのような点で迷っているのかを改めて確認できました。思わぬところで操作に迷いが発生していることを確認できるなど有意義な情報を得られるReplayが多かったです。
しかし、このような監視は[clarity](https://clarity.microsoft.com/)のような専用のツールに比べてできないことが多いのでそれを目的とした利用は他のツールで行うことがおすすめです。

## おわりに
Session Replayの利用を開始したので、その導入方法と感想を紹介しました。
この記事では紹介しきれませんでしたが、Session Replayのセッションを手動で操作したりその他の細かい設定が可能です。
ユーザーが操作した手順を4次元的に確認できるので、これまで以上に素早い調査と改修が可能になると考えられます。料金体系も良心的ですので興味があれば試してみてください。