コンテンツにスキップ

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 パッケージでも同じ設定を使用します:

import { datafluxRum } from "@cloudcare/browser-rum-slim"

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 に直接接続する場合は、siteclientTokendatakitOrigin に置き換えてください。両方のレポートアドレスを同時に設定しないでください。

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 として生成されます:

type = resource
resource.type = websocket

Resource は以下のタイミングで生成されます:

  1. ブラウザが WebSocket close イベントを受信したとき
  2. 現在の RUM セッションが期限切れになったとき
  3. ページが beforeunload をトリガーしたとき
  4. SDK が現在の収集インスタンスを停止したとき

WebSocket は永続接続です。接続がまだ開いている間は、Network に最終的な RUM Resource が一時的に表示されないのは正常な動作です。SDK は現在のところ、定期的に接続スナップショットをアップロードしません。

ページのリフレッシュ、クローズ、または移動が発生した場合、SDK は beforeunload フェーズで可能な限り決済と送信を試みます。ページプロセスが強制終了されたり、ブラウザがクラッシュしたり、デバイスの電源が切れたりした場合、JavaScript が実行される機会がないため、最後の接続 Resource が失われる可能性があります。

正常クローズ

ブラウザが close を受信した場合:

resource.websocket.tracking_end_reason = close_event

イベントには、クローズコード、クローズ理由、was_clean が含まれます。

セッション期限切れ

セッションが期限切れになった場合、まだ開いている接続は現在のデータに基づいて決済されます:

resource.websocket.tracking_end_reason = session_end

この場合、ビジネス WebSocket はクローズされないため、クローズコード、クローズ理由、was_clean は存在しない可能性があります。新しいセッションが確立されると、SDK は同じ物理接続に対して新しい統計セグメントを開始し、同じ connection_id を保持し、メッセージカウントとセグメント時間をリセットします。

セッションが期限切れになり、まだ更新されていない間のメッセージは、どのセッションにもカウントされません。この期間中に新しく作成され、更新時にもまだ開いている接続は、新しいセッションの更新時点から統計が開始されます。

ページアンロード

ページが beforeunload をトリガーした場合:

resource.websocket.tracking_end_reason = page_exit

接続が必ずしもブラウザの close イベントをトリガーするとは限らないため、クローズフィールドは存在しない可能性があります。

ハンドシェイク失敗

接続が一度も open をトリガーせずに close に入った場合:

resource.websocket.handshake_succeeded = false

この場合、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:現在のセグメント開始時に存在していた View
  • end_view_id:クローズまたは決済時に存在していた View

セグメントがページをまたぐ場合、これらの 2 つの ID は異なる可能性があります。Resource は、セグメントの開始時刻に基づいて RUM イベントパイプラインに入ります。

レポートフィールド

beforeSendevent.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_statusresource_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_eventsession_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_maxsend() 呼び出し前のサンプリングピーク値であり、ブラウザの送信キューを継続的に監視した値ではありません。

クローズフィールド

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.isWebSocket = true
domainContext.webSocket = ネイティブ WebSocket インスタンス

domainContextbeforeSend コールバック内でのみ使用され、アップロードされることはありません。

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 として収集されます。

接続の検証

  1. ブラウザの開発者ツールを開き、ビジネス WebSocket が接続され、メッセージが生成されていることを確認します。
  2. 能動的に socket.close(1000, "done") を実行します。
  3. Network で /v1/write/rum をフィルタリングします。
  4. リクエストデータ内で resource_type=websocket を検索します。
  5. handshake_succeeded、メッセージ数、バイト数、クローズフィールドを確認します。

接続がずっとクローズされない場合は、セッションの期限切れを待って tracking_end_reason=session_end を確認できます。ページをリフレッシュすると、tracking_end_reason=page_exit が表示されるはずです。この送信は、ページ終了フェーズでのベストエフォート型のレポートです。

よくある質問

設定しても WebSocket Resource が表示されない

以下の順序で確認してください:

  1. enableExperimentalFeatures"track_websockets" を含む配列であること
  2. RUM が接続作成前に初期化されていること
  3. 現在のセッションが sessionSampleRate に該当していること
  4. 接続がすでにクローズされているか、セッションが期限切れになっていないこと
  5. beforeSendfalse を返していないこと
  6. 接続が 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 がありません。

フィードバック

このページは役に立ちましたか?