Coralogix RUMが初期ネットワークを奪うのを防ぐ
Coralogix RUMはロード中にビーコンを送信し、自身のLCPからネットワークを奪います。代わりにイベントをバッファリングし、ページ非表示時にフラッシュしましょう。

Coralogix RUMが初期ネットワークを奪うのを防ぐ
RUMツールの役割はただ1つ、ユーザーが実際に得る体験を測定することです。しかし、Coralogixはロード中にその逆を行います。initを呼び出した瞬間にビーコンの送信を開始するため、その呼び出しがメインバンドル内にある場合、SDKはロードとハイドレーションのウィンドウに最初のバッチを送信し、まさに測定しようとしているLCPからネットワークを奪ってしまいます。
このツールは最初に数値を悪化させ、その後でそれを報告します。これは本末転倒です。そのため、データをバッファリングし、ページから離れるときにCoralogix APIに送信する回避策を書きました(Core/Dashはデフォルトでこれを行っているので、より良いRUMツールを探しているなら乗り換えを検討してください)。 Table of Contents!
Coralogixは自身のページよりも自分が重要だと考えている
そのビーコンが何と競合しているかを見てください。ヒーロー画像。フォント。ページをハイドレーションするスクリプトです。光回線では気付かないかもしれません。しかし、ユーザー全員が光回線を利用しているわけではありません。スマートフォン、電車内、ホテルのWi-Fiなど、帯域幅が限られている環境では、そのビーコンがあなた自身のコンテンツと帯域幅を奪い合います。最も接続状態の悪い訪問者はそれに気付くでしょう。一体何のために??
そして、あなたを悩ませるべき部分がこれです。その初期データすべてを早期に送信する理由は何もありません。皆無です。データは現在進行中の訪問に関するものに過ぎません。誰もそれをライブで読んではいません(もしそうなら、本当に不気味です)。メモリ上に保持しておき、訪問が終了したときに送信すれば、コストもかからず、何も失われません。ロード中に送信することはデメリットしかありません。ページを遅くするだけで、何のメリットもありません。それは馬鹿げています。だから、主導権を取り戻しましょう。すべてのイベントをキャプチャし、訪問が終わるまで何も送信しないのです。

さて、愚痴はこれくらいにしましょう。修正の時間です。これがCoralogixを正しく動作させる方法です!
すべてをバッファリングし、何も送信しない
CoralogixはbeforeSendフックを提供しています。イベントを返すと送信され、nullを返すと破棄されます。したがって、まずイベントを配列にプッシュし、次にnullを返します。すべてのイベントがキャプチャされ、ネットワーク上には何も送信されません。
import { CoralogixRum } from '@coralogix/browser';
const PUBLIC_KEY = '<YOUR_PUBLIC_KEY>';
const APPLICATION = 'my-app';
// すべてのイベントをキャプチャし、ライブで送信しない。
const buffer = [];
CoralogixRum.init({
public_key: PUBLIC_KEY,
application: APPLICATION,
version: '1.0.0',
coralogixDomain: 'EU1',
beforeSend: (event) => {
buffer.push({ event, t: Date.now() }); // 今タイムスタンプを押し、後でフラッシュする
return null; // SDK自身のビーコンを抑制する
},
}); ドキュメントを読むとbeforeSendはエラー専用のフィルターのように見えますが、重要なものをキャッチできることを確認しました。そうではありません。初期化スナップショット、リソースのタイミング、すべてのWeb Vitals、ユーザーインタラクション、エラーなど、すべてのイベントタイプに対して発火します。SDKは、ページ全体を測定するという本来の仕事を継続します。フラッシュするように指示するまで、ネットワーク上で静かになるだけです。
終了時にフラッシュする
次に、ページが非表示になったときにバッファを送信します。ここで、単純な実装は失敗します。アンロード時に送信する教科書的な方法であるため、navigator.sendBeaconに手を伸ばすでしょう。しかし、ここでは機能しません。イングレスはAuthorization: Bearerヘッダーで認証を行いますが、sendBeaconはリクエストヘッダーを設定できません。trueを返し、サイレントに403エラーになります。代わりにkeepalive付きのfetchを使用してください。同じようにアンロード後も生き残り、ヘッダーを設定できます。
ビーコンがあなたから隠していたことがもう1つあります。それは、イングレスが生のイベントを受け取らないということです。SDKは各イベントをスパンでラップし、{ logs: [...] }としてPOSTします。したがって、送信する前にその形を再構築してください。
const INGRESS = 'https://ingress.eu1.rum-ingress-coralogix.com/browser/v1beta/logs';
// coralogixDomainに合わせてeu1をお住まいのリージョン(us1, us2, eu2, ap1...)に置き換えてください
// イングレスは生のイベントではなく、SDKのスパンの形を要求します。再構築します。
function toCxSpan({ event, t }) {
const hasStack = !!(event.error_context
&& event.error_context.original_stacktrace
&& event.error_context.original_stacktrace.length);
return {
version_metadata: event.version_metadata,
applicationName: APPLICATION,
subsystemName: 'cx_rum',
severity: (event.event_context && event.event_context.severity) || 3,
isErrorWithStacktrace: hasStack,
timestamp: t,
text: { cx_rum: Object.assign({}, event, { timestamp: t }) },
};
}
function flush() {
if (!buffer.length) return;
const logs = buffer.splice(0).map(toCxSpan); // ドレイン: 2回目の呼び出しでは何も送信されません
fetch(INGRESS, {
method: 'POST',
keepalive: true, // アンロード後も生き残り、sendBeaconとは異なりヘッダーを設定できます
headers: {
'Authorization': 'Bearer ' + PUBLIC_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ logs, skip_enrichment_with_ip: false }),
}).catch(function () {});
}
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'hidden') flush();
});
window.addEventListener('pagehide', flush); spliceはバッファをドレイン(空に)するため、2回目の非表示イベントでは何も送信されません。unloadが発火しないモバイルにおいてすら、非表示へのvisibilitychangeは信頼できるシグナルです。pagehideはそのバックストップ(最後の砦)です。1つ注意点があります。keepaliveは実行中のリクエスト全体で64KBの予算を共有するため、何千ものリソースエントリをバッファリングする長いセッションでは、オーバーフローする可能性があります。大量に収集する場合は、logs配列をいくつかの小さなPOSTに分割(チャンク化)してください。
その代償
あなたは今、Coralogixのフォーマットを手動で再構築しています。注意してください! ここでのsession_contextは、SDK独自のものよりも少し薄くなります。CoralogixはセッションID、ユーザーエージェント、デバイス情報を後から( beforeSendの実行後に)入力するため、手動で構築したスパンには、通常のビーコンよりもこれらの詳細情報が含まれなくなります。Core Web Vitalsのキャプチャには関係ありません。詳細なセッション分析には影響する可能性があります。また、最初のデプロイ時には、ネットワークタブで200が返ってくることを確認してください。キーが間違っていたり、CORSルールが厳格化されていたりすると、ビーコンの時と同じようにサイレントに失敗するからです。
自分が所有していないワイヤーフォーマットを維持することが面倒に思える場合、率直な代替案は、ハイドレーション後までCoralogixRum.init()を遅延させ、そこからSDKに通常通り送信させることです。初期化前のロードメトリクスは失われますが、正気を保つことができます。どちらを取るか選んでください。

