WebSocket 永続接続収集¶
RUM SDK 3.3.6 以降では、ブラウザのネイティブ WebSocket 接続を RUM Resource として集約し、ハンドシェイク、メッセージトラフィック、インバウンドアイドル、送信バックログ、クローズ状態を分析できるようになりました。
この機能は現在実験的な機能であり、デフォルトでは無効になっています。SDK は WebSocket メッセージの本文を読み取ったりアップロードしたりすることはありません。
収集を有効にする¶
NPM¶
import { datafluxRum } from "@cloudcare/browser-rum"
datafluxRum.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "websocket-client",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
enableExperimentalFeatures: ["track_websockets"],
})
スリム版 RUM パッケージでも同じ設定を使用します:
CDN¶
<script
src="https://static.guance.com/browser-sdk/v3/dataflux-rum.js"
type="text/javascript"
></script>
<script>
window.DATAFLUX_RUM &&
window.DATAFLUX_RUM.init({
applicationId: "<APPLICATION_ID>",
site: "<PUBLIC_OPENWAY_URL>",
clientToken: "<CLIENT_TOKEN>",
service: "websocket-client",
env: "production",
version: "1.0.0",
sessionSampleRate: 100,
enableExperimentalFeatures: ["track_websockets"],
})
</script>
上記の例ではパブリック OpenWay を使用しています。DataKit に直接接続する場合は、site と clientToken を datakitOrigin に置き換えてください。両方のレポートアドレスを同時に設定しないでください。
enableExperimentalFeatures は配列である必要があります。文字列 "track_websockets" を直接指定しても収集は有効になりません。
初期化のタイミング¶
RUM は、業務が WebSocket 接続を作成する前に初期化する必要があります:
datafluxRum.init({
// その他の設定
enableExperimentalFeatures: ["track_websockets"],
})
const socket = new WebSocket("wss://example.com/socket")
以下の接続は収集されません:
- RUM 初期化前に作成された接続
- 初期化前にキャッシュされた元の
WebSocketコンストラクタを使用して作成された接続 - Web Worker または Service Worker 内で作成された接続
window.WebSocketを経由しないその他のトランスポート実装WebSocketStreamで作成された接続
収集を有効にしても、ネイティブ WebSocket の構築方法、静的定数、instanceof、ビジネスイベントリスナー、send() の戻り値の動作は変更されません。
収集モデル¶
各 WebSocket セッションセグメントは、1 つの RUM Resource として生成されます:
Resource は以下のタイミングで生成されます:
- ブラウザが WebSocket
closeイベントを受信したとき - 現在の RUM セッションが期限切れになったとき
- ページが
beforeunloadをトリガーしたとき - SDK が現在の収集インスタンスを停止したとき
WebSocket は永続接続です。接続がまだ開いている間は、Network に最終的な RUM Resource が一時的に表示されないのは正常な動作です。SDK は現在のところ、定期的に接続スナップショットをアップロードしません。
ページのリフレッシュ、クローズ、または移動が発生した場合、SDK は beforeunload フェーズで可能な限り決済と送信を試みます。ページプロセスが強制終了されたり、ブラウザがクラッシュしたり、デバイスの電源が切れたりした場合、JavaScript が実行される機会がないため、最後の接続 Resource が失われる可能性があります。
正常クローズ¶
ブラウザが close を受信した場合:
イベントには、クローズコード、クローズ理由、was_clean が含まれます。
セッション期限切れ¶
セッションが期限切れになった場合、まだ開いている接続は現在のデータに基づいて決済されます:
この場合、ビジネス WebSocket はクローズされないため、クローズコード、クローズ理由、was_clean は存在しない可能性があります。新しいセッションが確立されると、SDK は同じ物理接続に対して新しい統計セグメントを開始し、同じ connection_id を保持し、メッセージカウントとセグメント時間をリセットします。
セッションが期限切れになり、まだ更新されていない間のメッセージは、どのセッションにもカウントされません。この期間中に新しく作成され、更新時にもまだ開いている接続は、新しいセッションの更新時点から統計が開始されます。
ページアンロード¶
ページが beforeunload をトリガーした場合:
接続が必ずしもブラウザの close イベントをトリガーするとは限らないため、クローズフィールドは存在しない可能性があります。
ハンドシェイク失敗¶
接続が一度も open をトリガーせずに close に入った場合:
この場合、setup_duration はコンストラクトからクローズまたはセッション決済までの時間を示し、正常なハンドシェイクにかかった時間を示すものではありません。ブラウザは通常、異常クローズを示すためにクローズコード 1006 を使用します。実際の値はブラウザのイベントに依存します。
メッセージ統計¶
SDK はメッセージ数とバイト数のみを統計し、本文は収集しません:
| メッセージタイプ | バイト計算方法 |
|---|---|
| string | UTF-8 バイト数 |
ArrayBuffer |
byteLength |
TypedArray、DataView |
現在のビューの byteLength |
Blob |
size |
| 認識できないタイプ | 0 |
例えば、文字列 你好 は UTF-8 で 6 バイトとして統計され、JavaScript の文字列長である 2 ではありません。
View の所属¶
1 つの WebSocket セッションセグメントは、複数の RUM View にまたがる可能性があります。Resource は追加で以下の情報を記録します:
start_view_id:現在のセグメント開始時に存在していた Viewend_view_id:クローズまたは決済時に存在していた View
セグメントがページをまたぐ場合、これらの 2 つの ID は異なる可能性があります。Resource は、セグメントの開始時刻に基づいて RUM イベントパイプラインに入ります。
レポートフィールド¶
beforeSend で event.resource.websocket を読み取ることができます。最終的な intake では、フィールドは resource_websocket_* に変換されます。
基本 Resource フィールド¶
beforeSend パス |
intake フィールド | 説明 | 単位 |
|---|---|---|---|
resource.type |
resource_type |
固定で websocket |
- |
resource.url |
resource_url |
ブラウザが解決した ws:// または wss:// URL |
- |
resource.url_host |
resource_url_host |
URL のホスト | - |
resource.url_path |
resource_url_path |
URL のパス | - |
resource.url_query |
resource_url_query |
URL のクエリパラメータ | - |
resource.duration |
duration |
現在のセッションセグメントの長さ | ns |
WebSocket Resource には HTTP レスポンスがないため、resource_status、resource_method、TTFB、ダウンロードサイズ、HTTP タイミングはありません。
接続フィールド¶
resource.websocket.* |
intake フィールド | 説明 | 単位 |
|---|---|---|---|
connection_id |
resource_websocket_connection_id |
物理接続の一意の ID。セッションセグメント間で不変 | - |
handshake_succeeded |
resource_websocket_handshake_succeeded |
open を受信したかどうか |
boolean |
start_time |
resource_websocket_start_time |
現在のセグメントの開始時間 | Unix ms |
end_time |
resource_websocket_end_time |
クローズまたは決済時間 | Unix ms |
start_view_id |
resource_websocket_start_view_id |
セグメント開始時の View ID | - |
end_view_id |
resource_websocket_end_view_id |
接続終了時の View ID | - |
tracking_end_reason |
resource_websocket_tracking_end_reason |
close_event、session_end、または page_exit |
- |
protocol |
resource_websocket_protocol |
サーバーがネゴシエートしたサブプロトコル | - |
setup_duration |
resource_websocket_setup_duration |
最初のセグメントではコンストラクトから open までの時間。更新セグメントでは 0 |
ns |
メッセージフィールド¶
resource.websocket.* |
intake フィールド | 説明 | 単位 |
|---|---|---|---|
messages_in.count |
resource_websocket_messages_in_count |
インバウンドメッセージ数 | count |
messages_in.size |
resource_websocket_messages_in_size |
インバウンドメッセージの総バイト数 | byte |
messages_out.count |
resource_websocket_messages_out_count |
正常に send() を呼び出した回数 |
count |
messages_out.size |
resource_websocket_messages_out_size |
アウトバウンドメッセージの総バイト数 | byte |
time_to_first_message_in |
resource_websocket_time_to_first_message_in |
open から最初のインバウンドメッセージまで |
ns |
time_to_first_message_out |
resource_websocket_time_to_first_message_out |
open から最初のアウトバウンドメッセージまで |
ns |
last_message_in_at |
resource_websocket_last_message_in_at |
最後のインバウンドメッセージの時間 | Unix ms |
longest_inbound_silence |
resource_websocket_longest_inbound_silence |
隣接するインバウンドメッセージ間の最長間隔 | ns |
inbound_idle_duration_before_close |
resource_websocket_inbound_idle_duration_before_close |
最後のインバウンドメッセージからクローズまたは決済までの時間 | ns |
buffered_amount_max |
resource_websocket_buffered_amount_max |
各 send() 呼び出し前に観測された bufferedAmount のピーク値 |
byte |
buffered_amount_max は send() 呼び出し前のサンプリングピーク値であり、ブラウザの送信キューを継続的に監視した値ではありません。
クローズフィールド¶
resource.websocket.* |
intake フィールド | 説明 |
|---|---|---|
close_code |
resource_websocket_close_code |
ブラウザの CloseEvent のクローズコード |
close_reason |
resource_websocket_close_reason |
クローズ理由 |
was_clean |
resource_websocket_was_clean |
ブラウザが接続を正常にクローズしたとみなすかどうか |
セッションの期限切れやページアンロードによる決済時には、これらのフィールドは存在しない可能性があります。
beforeSend の使用¶
WebSocket Resource をチェック、補完、またはフィルタリングできます:
datafluxRum.init({
// その他の設定
enableExperimentalFeatures: ["track_websockets"],
beforeSend(event, domainContext) {
if (
event.type === "resource" &&
event.resource?.type === "websocket"
) {
event.context = {
...event.context,
socket_channel: "notifications",
}
console.debug(
"WebSocket completed",
event.resource.websocket,
domainContext?.webSocket
)
}
return true
},
})
WebSocket Resource の domainContext には以下が含まれます:
domainContext は beforeSend コールバック内でのみ使用され、アップロードされることはありません。
false を返すことで、特定の接続を破棄できます:
beforeSend(event) {
if (
event.type === "resource" &&
event.resource?.type === "websocket" &&
event.resource.url.includes("/health-stream")
) {
return false
}
return true
}
プライバシーとセキュリティ¶
SDK は完全な WebSocket URL を収集し、URL のクエリパラメータを解析します。パスワード、長期間有効なトークン、ID 番号などの機密値を URL に配置しないでください。
収集を有効にしても、ページの CSP connect-src、サーバー側の Origin 検証、その他のブラウザのセキュリティポリシーはバイパスされません。また、ハンドシェイクリクエストにカスタムトレースヘッダーが注入されることもありません。
サードパーティライブラリが RUM の初期化後に window.WebSocket を呼び出す限り、その基盤となる接続は収集されます:
- 自動再接続によって新しい接続が作成されるたびに、新しい
connection_idと Resource が生成されます。 - 1 つの接続が複数のビジネストピックを再利用する場合、SDK は接続レベルの集約のみを提供します。
- HTTP long polling フェーズは、引き続き XHR または fetch Resource として収集されます。
接続の検証¶
- ブラウザの開発者ツールを開き、ビジネス WebSocket が接続され、メッセージが生成されていることを確認します。
- 能動的に
socket.close(1000, "done")を実行します。 - Network で
/v1/write/rumをフィルタリングします。 - リクエストデータ内で
resource_type=websocketを検索します。 handshake_succeeded、メッセージ数、バイト数、クローズフィールドを確認します。
接続がずっとクローズされない場合は、セッションの期限切れを待って tracking_end_reason=session_end を確認できます。ページをリフレッシュすると、tracking_end_reason=page_exit が表示されるはずです。この送信は、ページ終了フェーズでのベストエフォート型のレポートです。
よくある質問¶
設定しても WebSocket Resource が表示されない¶
以下の順序で確認してください:
enableExperimentalFeaturesが"track_websockets"を含む配列であること- RUM が接続作成前に初期化されていること
- 現在のセッションが
sessionSampleRateに該当していること - 接続がすでにクローズされているか、セッションが期限切れになっていないこと
beforeSendがfalseを返していないこと- 接続が Worker によって作成されていないこと
WebSocket error を受信したが、Resource がまだない¶
SDK は close またはセッション決済時に最終イベントを生成します。error イベントだけで個別に決済することはありません。
handshake_succeeded=false¶
ブラウザが open をトリガーしませんでした。WebSocket URL、TLS 証明書、CSP connect-src、リバースプロキシの Upgrade 設定、サーバー側の Origin 検証、認証を確認してください。
メッセージサイズが 0¶
データ型が string、ArrayBuffer、TypedArray、DataView、または Blob であることを確認してください。SDK は任意のオブジェクトをシリアライズしてサイズを推定することはありません。
HTTP ステータスコードが表示されない¶
ブラウザの WebSocket API は、ページにハンドシェイクの HTTP ステータスコードを公開しません。そのため、WebSocket Resource には resource_status がありません。