セッションリプレイの収集原理とデータの完全性¶
セッションリプレイ(Session Replay)は、ユーザーが Web ページ上で行った操作プロセスを再現するために使用されます。これは画面録画ではありません。ブラウザ SDK がページの完全なスナップショットとその後の変化を記録し、データを圧縮して分割アップロードします。再生時には、プラットフォームがこれらのデータに基づいてページを再構築します。
この点を理解することで、以下の3つの現象を区別するのに役立ちます。
- 収集されていない:録画が開始されていない、サンプリングに該当しない、またはブラウザの機能が不足している。
- 収集経路に欠損が発生:ページの変化が保護予算を超えた、ネットワークが永続的に失敗した、またはページが突然閉じられた。
- データはアップロード済みだが視覚的に不完全:画像、フォント、スタイルが再生時にアクセス不可、またはコンテンツがプライバシールールと機能制限の影響を受けている。
データの生成方法¶
初期化して録画を開始
↓
セッションサンプリングと録画資格の判定
↓
完全スナップショット(ページベースライン)
↓
DOM、入力、スクロール、マウス、スタイル、Canvas 等の増分
↓
圧縮して順序付けられたセグメントを生成
↓
通常のネットワーク送信;ページ離脱時は beacon / XHR を試行
↓
プラットフォームで処理し、再生可能なファイルを生成
1. 初期化とサンプリング¶
SDK init() が完了した後、明示的に呼び出す必要があります。
呼び出し前に発生したページの状態や操作は、遡って補完録画されることはありません。録画が実際に開始されるかどうかは、現在の Session が sessionReplaySampleRate または sessionReplayOnErrorSampleRate に該当するかどうかにも依存します。
以下を使用して、現在のページが録画状態に入っているかどうかを確認できます。
startSessionReplayRecording({ force: true }) を使用すると、現在の Session に強制的に再生資格を持たせることができます。このオプションはサンプリング動作を変更するため、強制的に録画する必要がある明確なビジネスシナリオでのみ使用することを推奨します。
2. 完全スナップショット¶
録画が開始されると、SDK は最初に再生可能なページベースラインを生成します。これには以下が含まれます。
- 現在のページアドレスとビューポート
- フォーカス状態
- DOM 構造、属性、テキスト、スクロール位置
- ブラウザがサポートする場合の Visual Viewport 情報
完全スナップショットの生成中に、ページの DOM が依然として急速に変化している場合、SDK は異なる時間状態が混在したスナップショットを破棄し、再構築します。非常に大きなページや継続的に高頻度で変化するページでは、複数回失敗する可能性があります。連続した復旧に失敗した場合、SDK は現在のページの録画を停止し、正しく再生できないデータが生成され続けるのを防ぎます。
3. 増分記録¶
完全スナップショットの後、SDK は継続的に以下を記録します。
- DOM ノードの追加、削除、テキストおよび属性の変更
- マウス、タッチ、クリック、スクロール
- 入力フィールドの値の変化
- ビューポートサイズの変化
- 音声・動画要素の再生、一時停止、および進行状態
- スタイルルールの変更
- 有効化された Canvas の記録
これらの増分は、以前の完全スナップショットに依存します。例えば、増分がノード ID を参照しているが、対応するベースラインが正常にアップロードされていない場合、再生側はこの変更を正しく適用できません。
4. セグメント化とアップロード¶
SDK は記録を圧縮して順序付けられたセグメントにします。通常の録画時、セグメントはおおよそ約5秒ごと、内部サイズ目標に近づいたとき、View の切り替えが発生したとき、またはページライフサイクルが変化したときにリフレッシュされます。
通常のネットワーク障害は、順番にメモリ内の再試行キューに入ります。オフライン、HTTP 408、429、5xx は再試行されます。他のほとんどの 4xx は再試行不可のエラーであり、対応するセグメントは永久に破棄されます。
特定のセグメントが配信不可と判断された場合、SDK はそれに依存する同じベースライン世代を無効にし、新しい完全スナップショットの生成を試みます。新しいスナップショットが成功すると、その後のページ状態は再生を継続できますが、永久に失われたセグメントがカバーする操作プロセスは補完できません。
エラーリプレイでエラー前のデータを保持する方法¶
sessionReplayOnErrorSampleRate を設定すると、該当する Session はまずブラウザメモリ内にロックされたリプレイセグメントを保存します。エラーが発生した後、SDK はロックを解除して最近のページベースラインと増分をアップロードし、Session が終了するまで録画を継続します。
これは、エラー発生前の最大約1分間のコンテキストを提供するものであり、無制限の履歴を提供するものではありません。
- Session でエラーが発生しなかった場合、ロックされたデータはアップロードされません。
- エラー発生前にページが閉じられた場合、メモリ内のデータはアップロード経路に入りません。
- メモリキャッシュが保護上限に達した場合、SDK は新しい完全スナップショットから再生可能なベースラインを再構築します。
したがって、エラーリプレイはエラー発生前の操作の特定に適しており、すべてのエラーのない Session を保存する通常のリプレイの代替には適していません。
DOM データが欠落する可能性がある場合¶
ブラウザ SDK は、セッションリプレイが長時間メインスレッドを占有するのを防ぐために、シリアライゼーションとキャッシュに保護境界を設定しています。現在の実装では、完全スナップショットは最大20万ノードを処理し、推定サイズは約4 MiB です。DOM ツリーの深さ、単一ノードの属性数、テキスト長、スタイルルール、増分キューにもそれぞれ境界があります。
以下のシナリオでは、切り詰め、破棄、またはベースラインの再構築が発生する可能性があります。
- ページが一度に非常に大きな DOM サブツリーを作成または置換する。
- 単一のテキスト、属性、またはインラインスタイルが異常に大きい。
- 高頻度の DOM 更新が長時間続き、安定したスナップショットが得られない。
- Mutation 増分の生成速度が SDK の処理速度を継続的に上回る。
- ページに多数の Shadow Root、スタイルルール、および巨大なリストが同時に含まれている。
- ブラウザが DOM または CSSOM の読み取り自体で長時間ブロックされる。
SDK は構造変更の半分だけを送信することはありません。分割不可能な DOM 変更が大きすぎる場合、その変更全体を破棄し、新しい完全スナップショットを要求します。これにより、その後のページの一貫した状態を回復できますが、欠損期間中のすべての中間ステップを回復することはできません。
上記の数値は、現在の SDK の内部保護しきい値であり、設定可能な項目ではなく、長期的に安定した公開 API としても提供されません。調査時には、実際に使用している SDK バージョンを基準にしてください。
プライバシールールによる予期される欠落¶
デフォルトのプライバシーレベルは mask-user-input です。以下のデータはマスク、非表示、またはプレースホルダコンテンツに置き換えられる可能性があります。
- パスワード、メールアドレス、電話番号、非表示入力
- クレジットカードの自動入力関連フィールド
- プライバシー属性またはプライバシークラス名でマークされたノード
shouldMaskNodeがマスクすべきと返すカスタムノード- スクリプトコンテンツと非表示ノードのサブツリー
このようなコンテンツの欠落は、データセキュリティポリシーによるものであり、ネットワークパケットロスではありません。「入力が空である」または「特定の領域にコンテンツがない」という問題を調査する際は、まずプライバシー設定を確認してください。
HTML と Shadow DOM の機能限界¶
現在の収集範囲は以下の通りです。
| コンテンツ | 収集状況 |
|---|---|
| 通常の DOM | 対応 |
| open Shadow DOM | アクセス可能な構造、変更、および関連スタイルに対応 |
| closed Shadow DOM | 収集は保証されません |
| Web Components | Shadow Root がオープンかどうか、および内部で使用されるコンテンツタイプに依存 |
| iframe | iframe 要素自体は記録可能ですが、完全な再現のための内部ドキュメントは記録しません |
| video / audio | 要素と再生状態は記録可能ですが、メディアトラックやフレーム単位のビデオコンテンツは収集しません |
Canvas と WebGL でフレーム落ちが発生する理由¶
Canvas の録画はデフォルトでオフになっています。以下の条件をすべて満たす必要があります。
- Session Replay がサンプリングに該当し、録画中であること。
replayCanvasEnabled: trueであること。- 対象の Canvas が収集可能な DOM に存在すること。
- WebGL/WebGL2 シーンに WebGL Replay プラグインが追加で登録されていること。
Canvas の自動録画は予算ベースのスケジューリングを採用しており、フレーム単位の収集を保証しません。以下の状況では、視覚的なフレーム欠損が発生する可能性があります。
- アニメーション速度が収集リズムより速い。
- ページが非表示になり、自動スケジューリングが一時停止する。
- 複数の Canvas が公平なローテーションまたは同時エンコードを待機している。
- 画面に変化がなく、バックオフが発生する。
- Canvas のサイズ、エンコード結果、または単一のコマンドが大きすぎる。
- Canvas がまだ DOM に接続されていない、またはその DOM ベースラインがまだ公開されていない。
- WebGL プラグインがエンジンの Context 作成、描画メソッドのキャッシュ後に初期化された。
- 最後の WebGL 描画がクールダウンまたはエンコード中に発生し、その後に収集をトリガーする新しい描画がない。
WebGL Replay は、描画駆動型の予算ベースのピクセルスナップショットであり、WebGL コマンドレベルのリプレイやフレーム単位のビデオではありません。詳細な設定とパフォーマンスの境界については、Canvas 録画の導入方法 を参照してください。
ページ終了時に末尾データが失われやすい理由¶
リプレイのエンコード結果と再試行キューは、ブラウザのメモリ内にのみ保持されます。ページが非表示、フリーズ、またはアンロードされると、SDK は保留中のレコードを積極的にリフレッシュし、sendBeacon または XHR を介した配信を試みます。
終了フェーズでも、以下の制限が存在します。
- ブラウザが JavaScript に割り当てる時間は非常に短い。
- 終了フェーズには制限された送信予算があり、送信待ちデータが多すぎると末尾が破棄される。
sendBeacon()が成功を返すのは、ブラウザがキューイングされたタスクを受け入れたことを意味するだけで、サーバー側が永続化したことを意味するわけではない。- ブラウザの強制終了、ブラウザクラッシュ、モバイルシステムによるプロセス回収、停電、またはネットワーク切断により、メモリキューは直接クリアされる。
- ページが閉じられる前にロックが解除されていないエラーリプレイデータはアップロードされない。
重要なデータの信頼性のある配信を beforeunload に完全に依存しないでください。早期に録画を開始し、重要な操作後にページが正常な送信時間を確保できるようにすることは、ページ離脱ロジックを追加するよりも効果的です。
データはアップロード済みなのに、なぜ再生が不完全なのか¶
セッションリプレイは DOM とリソースアドレスに基づいてページを再構築し、すべての画像、フォント、外部スタイルをリプレイデータに完全にパッケージ化することはありません。リプレイセグメントがすべて正常にアップロードされた場合でも、以下の理由により表示異常が発生する可能性があります。
- 画像、フォント、またはスタイルリソースが既に利用不可になっている、またはアドレスが変更されている。
- リソースにログイン状態、署名、または内部ネットワークアクセスが必要である。
- CORS が再生ページによるリソースの読み込みを許可していない。
- CSP が Worker、Blob URL、またはリソースの読み込みをブロックしている。
- クロスオリジンのスタイルシートの CSSOM は読み取り不可であり、再生時には元のリンクを再リクエストする必要がある。
- プラットフォーム側のデータ処理、インデックス作成、またはリプレイファイルの生成が未完了、または失敗している。
リソースの問題は、通常、DOM 構造は存在するものの、フォント、画像、レイアウト、またはホバースタイルが正しくないという形で現れます。
データ欠損の分類¶
| 分類 | よくある原因 | その後継続できるか |
|---|---|---|
| 未録画 | 開始 API が呼び出されていない、サンプリングされていない、ブラウザが非対応 | 正常に開始できれば記録可能、それ以前は補完不可 |
| 先頭部分の欠落 | SDK の初期化または録画開始が遅すぎる | 以降は継続可能、先頭部分は補完不可 |
| プライバシーマスク | デフォルトのプライバシールールまたはカスタムマスク | 予期される動作であり、原文を復元すべきではない |
| 機能限界 | closed Shadow DOM、iframe 内ドキュメント、メディアコンテンツ、Canvas 未有効 | 非対応データは補完不可 |
| DOM 保護境界 | ページが大きすぎる、継続的な変動、増分キューオーバーフロー | 新しい完全スナップショット後は一貫性を回復可能、欠損プロセスは補完不可 |
| Canvas スケジュール境界 | クールダウン、バックオフ、ページ非表示、エンコードまたはサイズ制限 | 後続のスナップショットで現在の画面は回復可能、中間フレームは保証されない |
| Worker/エンコード失敗 | CSP、Worker 作成失敗、エンコード例外、または継続的なバックプレッシャー | 録画を再開することで回復する可能性あり |
| ネットワーク永続的失敗 | 再試行不可の 4xx、メモリキュー満杯、プロキシによるインターセプト |
新しいベースライン後は継続可能、古いセグメントは補完不可 |
| ページ突然終了 | 強制終了、クラッシュ、システム回収、終了時間不足 | 末尾は通常補完不可 |
| リソース読み込み失敗 | CORS、認証、リソース期限切れ、または CSP | リソースのアクセス性を修正することで表示が改善される可能性あり |
| プラットフォーム処理異常 | アップロード成功だが処理またはファイル生成に失敗 | サーバー側の処理結果に依存 |
調査方法¶
以下の順序で確認することを推奨します。
- 録画資格:サンプリングレートを確認し、
startSessionReplayRecording()を呼び出しているか確認し、isRecording()をチェックします。 - Session と View:
getInternalContext()を実行し、Application ID、Session ID、View ID が存在し、期待通りであることを確認します。 - クライアントリクエスト:ブラウザの開発者ツールで
/v1/write/rum/replayをフィルタリングし、リクエスト時間、ステータスコード、レスポンス、失敗理由を記録します。 - Worker とセキュリティポリシー:コンソール内の Worker、Blob URL、CSP、Canvas エンコードエラーを確認します。
- プライバシーと機能限界:欠損領域がマスク、closed Shadow DOM、iframe、音声・動画、または未有効の Canvas に該当するか確認します。
- リソースのアクセス性:再生環境から画像、フォント、CSS URL の有効期限、認証、CORS、CSP を検証します。
- プラットフォーム処理状態:クライアントリクエストが成功したにもかかわらずデータがない場合、Session ID、Application ID、発生時刻、SDK バージョン、リクエストレスポンスを記録して調査を続行します。
データ欠損を減らすための推奨事項¶
- SDK を早期に初期化し、録画を開始する。
- ビジネス量に基づいて、通常のリプレイとエラーリプレイのサンプリングレートを明確に設定する。
- 巨大な DOM サブツリー、テキスト、属性、インラインスタイルを一度に書き込まない。
- 大規模なリストや高頻度のページ状態は、バッチで更新する。
- 画像、フォント、CSS に安定したアドレスを提供し、CORS と CSP を正しく設定する。
- 必要なページでのみ Canvas を有効にし、シナリオに応じて手動、自動スナップショット、または高再現度モードを選択する。
- WebGL エンジン起動前に WebGL Replay プラグインを初期化する。
/v1/write/rum/replayの4xx、429、5xx、およびネットワーク障害を監視する。- 調査時には、Session ID、View ID、SDK バージョン、ブラウザバージョン、ページライフサイクル情報を保持する。