アプリケーションメトリクスを使用して戻る/進むキャッシュを測定する

bfcacheMetricsIntegration は 3 つの bfcache 指標を Sentry に送る。記事は計測の仕組みと、どの数字を見れば戻る・進むのキャッシュが効いていると分かるかを説明する。

日本語
コピー
Measuring the back/forward cache with Application Metrics 的题图

この盲点こそ、私たちが狙った的だ。アプリケーションメトリクスをリリースしたことで、名前のつくブラウザシグナルはすべてグラフに描ける数値になった。そこで、他のテレメトリ型(span など)では決して浮かび上がってこなかった重要なシグナルを探し始めた。筆頭が bfcache だった。その成果が新しい bfcacheMetricsIntegration だ。ブラウザが毎日ほとんど音もなく何千回も下している判断を、計測でき、追跡でき、修正できるものに変える。

bfcache が主要な体験にどう影響するか

ページを離れるとき、ブラウザは通常そのページを破棄する。スクリプトは停止し、メモリは解放され、DOM は消える。戻ってくるとページはゼロから再構築され、リスナーが再登録され、fetch リクエストが飛び交い、ローディングアニメーションが回り続ける。

bfcache はこれをすべてショートカットする。ブラウザはページをその場で凍結し、DOM、JavaScript ヒープ、スクロール位置、そのすべてを含む完全なスナップショットをメモリ上に保持する。

進む/戻るナビゲーションが起きると、ブラウザはそのスナップショットを解凍してそのまま返す。読み込むものが何もないので、切り替えは事実上瞬時だ。ページは一度も消えていない。

これはニッチな最適化ではない。進む/戻るナビゲーションは Web 上で最も頻度の高い経路のひとつであり、体感速度がビジネス価値に直結するフローでは支配的だ。たとえば EC で商品ページと一覧ページを行き来する動き、検索結果ページの切り替え、ドキュメントサイト、メディアの閲覧、マーケットプレイス。ネットワークやデバイスが遅いユーザーほど恩恵は大きい。そうでなければ戻るボタンを押すたびにフルリロードのコストを払うことになるからだ。こうした経路では「戻るボタンがどれだけ速いか」は一級のパフォーマンス課題であるべきで、新規ページロードより重要なこともしばしばだ。

違いは並べて見るのが一番わかりやすい。ミスすればページ全体をゼロから再構築し、再リクエストし、再レンダリングし、ユーザーがいた位置も失われる。

見つけることの方が大事

パフォーマンスツールはどれもページロードのライフサイクルを前提に組まれていて、Sentry も例外ではない。通常のツールにとって、bfcache ヒットは何も起きていないのと区別がつかない。だから進む/戻るナビゲーションは検知されないことさえある。

ここにパラドックスがある。bfcache がうまく機能するほど、既存のツールが集めるデータは少なくなる。成功とは沈黙だからだ。見えないものは追跡できないし、ここでは最も健全な状態が痕跡を残さないことそのものだ(ダジャレのつもりだ)。

さらに厄介なのは、ブラウザが流動的なヒューリスティクスでページの bfcache 対象可否を決めることだ。自分のページが理由もなく対象外と判定されることがある。

対象外の理由はありふれている。unload リスナー、Cache-Control: no-store レスポンスヘッダー、閉じられていない接続、iframe に埋め込まれたインターセプターのいずれかが、ページをキャッシュの外に追い出した実例がある。これを読んでいる時点で、いくつかはもう当てはまらないかもしれないし、別の理由に置き換わっているかもしれない。あなた自身かサードパーティのスクリプトが、気づかないうちにそのどれかを加えている可能性がある。

つまり、対象可否は単純なコード変更で劣化することもあるし、コードが一切変わっていなくても劣化することがある。テストやコードレビューでこの劣化に立ち向かうのは現実的でない。これは本来、能動的に追跡して修正すべきものだ。

アプリケーションメトリクスはこうした問題の発見にうってつけで、span やログではできない芸当だ。ミスが急増したら、ルート別に分解し、リリース別に分解し、ブラウザ別に分解して、犯人を突き止めるまで掘り下げられる。「あれはどうなの」のひとつひとつがただのクエリであって、再デプロイも新しい計装の追加も要らない。

仕組み

ブラウザは実はすべて教えてくれている。pageshow イベントと notRestoredReasons API が、ページが bfcache の対象外かどうか、そしてその理由を正確に伝えてくれる。

bfcacheMetricsIntegration はこれらのシグナルを 3 つのアプリケーションメトリクスとしてモデル化する(ブラウザの対応状況による)。それぞれに属性がいくつか付く。

  • browser.bfcache.navigation はカウンターで、進む/戻るナビゲーションごとに 1 回記録され、次を伴う。

browser.bfcache.outcome:hit または miss。

  • browser.bfcache.not_restored_reason_count:ブラウザが報告した理由の数。

browser.bfcache.not_restored(Chromium のみ)はカウンターで、ミスごとに、復元されなかった理由 1 つにつき 1 回記録され、次を伴う。

  • browser.bfcache.reason:ブラウザが返す生の理由文字列。たとえば unload-listener、websocket、idbversionchangeevent、response-cache-control-no-store。
  • browser.bfcache.frame:ブロックが発生した場所。メインドキュメントなら top、子フレームなら child。

browser.bfcache.reload.duration はミリ秒単位の分布で、進む/戻るナビゲーションがミスしたとき、フォールバックのリロードがどれだけ高くついたかを表す。本当に指標に効いてくるのはここだ。復元が本来どれだけ速かったかを知っているとは主張していない。ミスがユーザーに実際にいくら払わせたかを測るので、ブロックの件数ではなく実際の痛みで優先順位をつけられる。

この 3 つに落ち着いたのは、合わせて進む/戻るナビゲーションの一連の流れに答えを出すからだ。復元されたか? なぜされなかったか? ミスのコストはいくらか?

使い方

1行のコードでこのインテグレーションを有効にできる:

import * as Sentry from "@sentry/browser";

Sentry.init({
 integrations: [
 // other integrations...
 Sentry.bfcacheMetricsIntegration(),
 ],
});

このインテグレーションが出力するのはアプリケーションのメトリクスだ。したがって、一部の疑問にしか答えられない出来合いのダッシュボードを押し付けることはせず、そのたびに調整が必要になることもない。ダッシュボードは自分で組み立ててもらう。 agentic dashboard creationを使えば、これらのメトリクスをもとに、見たいものを伝えるだけでいい。たとえばこんな具合だ:

  • 「bfcache のメトリクスを使って、全体の bfcache ヒット率と、過去1か月でそれが上がっているのか下がっているのかを見たい。」
  • 「bfcache のメトリクスを使って、どのルートが bfcache ミスを最も多く生んでいるかを見たい。優先的に直したいから。」
  • 「bfcache のメトリクスを使って、bfcache ミスの主な原因を見たい。全体でもいいし、特定のルートについてでもいい。」

ウィザードとの対話は続けられるので、納得がいくまでダッシュボードを調整できる。

設定手順の詳細と、メトリクスおよび属性の完全な一覧は bfcacheMetricsIntegration のドキュメントを参照。

戻るボタンを追跡し始める

このインテグレーションは明示的に有効化する必要があり、JavaScript SDK v11と同時にリリースされる。ヒットとミスの結果はモダンブラウザならどれでも取得できるので、自分の bfcache の状態は今日から測定できる。詳細な未復元理由は現時点では Chromium 固有の拡張機能だが、より多くのエンジンが notRestoredReasons API を実装すれば、カバレッジは自然に広がっていく。 私たちはさらに、これまでこうしたナビゲーションを一切カウントしてこなかった機能にも bfcache の認識を広げつつある。たとえば Core Web Vitals だ。復元されたページでは pageload が発火しないため、これらのメトリクスがそれを記録することはなかった。bfcache への対応はまさにこの穴を埋めるもので、こうしたカバレッジはユーザー自身に気づいてもらうのではなく、こちら側で組み込んでおきたい。Building Sentry's Laravel AI Integration

Sentry の Laravel AI インテグレーションを構築する

Agent Hackweek の期間中に、Laravel AI 向けのゼロコンフィグな Agent Tracing をどうやって作ったか——AI が生成した防御的なコードから、LLM 呼び出しと HTTP リクエストを対応付けるところまで。続きを読む agent tracing で AI 検索アシスタントをデバッグする

agent tracing で AI 検索アシスタントをデバッグする

私たちのチームが、Sentry 自身の AI Conversations 機能を使って自然言語検索アシスタントをどうデバッグしたか。続きを読む Application Metrics がサイズ推定器の間違いを捕まえた

Application Metrics がサイズ推定器の間違いを捕まえた

大事すぎてログに埋もれさせてはいけない数字があり、サンプリングで失われてもいけない数字がある。小さな動画コンバーターが、Application Metrics で KPI を追跡する最も分かりやすい例になった。続きを読む

Syntax.fm logo

Syntax Podcast を聴く

もちろん開発者向けポッドキャストのスポンサーもしている。いつも使っているプラットフォームで聴いてみてほしい。Syntax を聴く

出典: Sentry← ホームへ戻る