Observability

Datadog RUM とは?リアルユーザーモニタリングの概要と導入方法を学ぶ

Flaty

この記事で分かること

  • RUM(Real User Monitoring)とは何か、導入すると何が解決できるのか
  • Datadog RUM で取得できるデータの種類
  • React(SPA)と Next.js での RUM SDK の導入手順
  • RUM ダッシュボードの基本的な見方

はじめに

Web アプリケーションのパフォーマンスを改善するには、実際のユーザーがどのような体験をしているかを把握する必要があります。サーバーサイドのメトリクスだけでは、ネットワーク遅延やブラウザのレンダリング時間など、ユーザーが感じるパフォーマンスを正確に測定できません。

RUM(Real User Monitoring)は、実際のユーザーのブラウザ上でパフォーマンスデータを収集し、ユーザー体験を可視化する手法です。この記事では、Datadog RUM の概要と、React・Next.js での導入方法をまとめます。

RUM(Real User Monitoring)とは

RUM は、実際のユーザーのブラウザから直接パフォーマンスデータを収集するモニタリング手法です。

Synthetic Monitoring との違い

フロントエンドの監視手法には、RUM のほかに Synthetic Monitoring があります。両者の違いを整理します。

項目 RUM Synthetic Monitoring
データソース 実際のユーザーのブラウザ 人工的なテストリクエスト
カバレッジ すべてのページ・ユーザー操作 事前に定義したシナリオのみ
環境の多様性 実際のデバイス・ネットワーク環境を反映 固定された環境での実行
ユースケース ユーザー体験の全体把握、問題の発見 SLA 監視、リグレッション検知

RUM は「実際のユーザーが何を体験しているか」を把握するのに適しており、Synthetic Monitoring は「想定した条件で正しく動作するか」を検証するのに適しています。両者は補完的な関係にあります。

RUM で収集できるデータ

Datadog RUM では、以下のカテゴリのデータを自動的に収集します。

  • Sessions — 一人のユーザーがアプリケーションを開いてから離脱するまでの一連の行動を 1 セッションとして記録する。「ユーザーがどのページをどの順番で閲覧したか」をセッション単位で追えるため、離脱ポイントの分析やカスタマーサポートでの問い合わせ対応に活用できる
  • Views — ページ遷移(SPA ではルート変更)のたびに、そのページの表示パフォーマンスを自動計測する。たとえば「商品一覧ページの LCP が 3 秒を超えている」といったページ単位のボトルネックを Core Web Vitals(LCP、INP、CLS)の数値で把握できる(INP の計測には SDK v5.1.0 以降が必要)
  • Actions — ボタンのクリックやフォームの送信など、ユーザーの操作イベントを自動収集する。アクションごとの loading time を計測し、「購入ボタンを押してから画面が切り替わるまで 2 秒かかっている」のように、操作が完了するまでの体感時間を定量化できる
  • Resources — ページが読み込む API コール、画像、CSS、JS などのネットワークリクエストを個別に記録する。「特定の API レスポンスが P95 で 800ms かかっている」「未圧縮の画像が読み込み時間を押し上げている」といったリソース単位の問題を特定できる
  • Long Tasks — メインスレッドを 50ms 以上ブロックしているタスクを検出する。ユーザーが操作しても UI が反応しない「カクつき」の原因となっている重い処理を特定し、コード分割や処理の非同期化といった改善につなげられる
  • Errors — JavaScript の未捕捉例外やネットワークエラーを、スタックトレースとエラー発生時のユーザー操作履歴とともに記録する。「決済画面で TypeError が発生し、直前にクーポンコードを入力していた」のように、エラーの再現手順をセッションから追跡できる

RUM で解決できる課題

RUM を導入することで、サーバーサイドのモニタリングだけでは把握できなかった以下のような課題を解決できます。

「遅い」の原因がわからない — サーバーのレスポンスタイムは正常なのに、ユーザーから「遅い」という問い合わせがくることがあります。原因がネットワーク遅延なのか、ブラウザのレンダリングなのか、サードパーティスクリプトなのかは、サーバー側のメトリクスだけでは判断できません。RUM を使えば、実際のユーザー環境でのページ読み込み時間やリソースの Waterfall を確認し、ボトルネックを特定できます。

デプロイ後のリグレッションに気づけない — 新しいバージョンをデプロイした後に、JavaScript エラーの急増やパフォーマンスの悪化が起きていても、ユーザーからの報告がなければ気づけないことがあります。RUM のエラー率やパフォーマンス指標を version タグで追跡することで、デプロイ起因の問題を早期に検知できます。

エラーの影響範囲がわからない — エラーログにスタックトレースが残っていても、そのエラーが何人のユーザーに影響しているのかは通常わかりません。RUM の Error Tracking はエラーごとに影響を受けたセッション数を集計するため、優先度の判断に使えます。

フロントエンドとバックエンドが分断されている — フロントエンドのパフォーマンス問題がバックエンドの API 遅延に起因しているケースは多いですが、両者を横断的に分析する手段がなければ原因の切り分けが難しくなります。Datadog RUM は APM と連携でき、ユーザーのクリックからバックエンドの処理まで一つのトレースとして追跡できます。なお、RUM と APM を関連付けるにはトレース相関の設定が必要です。

Datadog RUM の導入

事前準備

Datadog RUM を利用するには、以下が必要です。

  1. Datadog アカウント(RUM はセッション数に応じた従量課金)
  2. RUM Application の作成(Datadog コンソールの Digital Experience > Performance Summary > New Application から作成)
  3. 作成時に発行される applicationIdclientToken

React(SPA)での導入

React アプリケーションに RUM SDK を導入する手順を説明します。

1. SDK のインストール

npm install @datadog/browser-rum

2. SDK の初期化

アプリケーションのエントリポイントで、React のレンダリングより前にモジュールレベルで SDK を初期化します。init() を可能な限り早いタイミングで呼ぶことで、初期ロード時の Core Web Vitals やエラーを取りこぼさずに計測できます。

// src/main.tsx (Vite) or src/index.tsx (CRA)
import { datadogRum } from "@datadog/browser-rum";

datadogRum.init({
  applicationId: "<APPLICATION_ID>",
  clientToken: "<CLIENT_TOKEN>",
  site: "datadoghq.com",
  service: "my-react-app",
  env: "production",
  version: "1.0.0",
  sessionSampleRate: 100,
  sessionReplaySampleRate: 20,
  trackUserInteractions: true,
  trackResources: true,
  trackLongTasks: true,
  defaultPrivacyLevel: "mask-user-input",
});

// datadogRum.init() の後に React をレンダリングする
// ReactDOM.createRoot(document.getElementById("root")!).render(<App />);

モジュールレベルのコードは JS エンジンの仕様上 1 回しか評価されないため、二重初期化を防ぐガードは不要です。useEffect 内で初期化する方法もありますが、コンポーネントのマウント後に実行されるため初期ロードのデータを取りこぼす可能性があります。

applicationIdenv などの値は実際のプロジェクトでは環境変数で管理してください(後述の「環境変数の管理」を参照)。

主要な設定項目を説明します。

  • site — Datadog のリージョンに対応するサイト URL。US1 は datadoghq.com、EU は datadoghq.eu、US3 は us3.datadoghq.com、AP1 は ap1.datadoghq.com など、利用中のリージョンに合わせて設定する
  • service / env / version — APM のトレースと紐付けるための識別子。バックエンドの Datadog APM と同じ命名規則を使うことで、フロントエンドからバックエンドまでの一気通貫のトレースが可能になる
  • sessionSampleRate — セッションのサンプリングレート(0〜100)。本番環境でのコスト管理に使用する
  • sessionReplaySampleRate — Session Replay を記録するセッションの割合(デフォルト: 0)。sessionSampleRate で抽出されたセッションに対して適用されるため、両者のバランスでコストと精度を調整する
  • trackUserInteractions / trackResources / trackLongTasks — Session Replay を使う場合は明示的に true を指定するのが安全。SDK のバージョン差異があるため、プロジェクトで使う SDK に合わせて設定する
  • defaultPrivacyLevel — Session Replay でのプライバシー設定。mask-user-input はフォーム入力をマスクする

3. ユーザー情報の紐付け(オプション)

ログイン後にユーザー情報を RUM セッションに紐付けると、特定ユーザーの体験を追跡できます。

datadogRum.setUser({
  id: "user-123",
  name: "Taro Yamada",
  email: "taro@example.com",
  plan: "premium",
});

送信したユーザー情報は Datadog のサーバーに保存されます。nameemail などの個人情報を含める場合は、プライバシーポリシーや GDPR 等の規制要件を確認したうえで、送信する属性を決定してください。

Next.js での導入

Next.js では、SSR の特性上 RUM SDK をクライアントサイドでのみ初期化する必要があります。Datadog の公式ガイドでは 3 つの導入方式が紹介されており、それぞれトレードオフがあります。

方式 イベント収集 パフォーマンス影響
NPM + Client Component ハイドレーション後から収集 小さい
CDN Sync (beforeInteractive) すべて収集 ページロードに影響あり
CDN Async ハイドレーション後から収集 小さい

この記事では NPM と CDN Sync の 2 つを紹介します。

方式 1: NPM + Client Component(App Router)

"use client" を指定したクライアントコンポーネント内で、モジュールレベルで init() を呼びます。init() に渡す設定オブジェクトは React の例と同様です。

// src/components/DatadogInit.tsx
"use client";

import { datadogRum } from "@datadog/browser-rum";

datadogRum.init({
  applicationId: process.env.NEXT_PUBLIC_DD_APPLICATION_ID!,
  clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN!,
  site: "datadoghq.com",
  service: "my-nextjs-app",
  env: process.env.NEXT_PUBLIC_DD_ENV ?? "production",
  version: process.env.NEXT_PUBLIC_DD_VERSION ?? "1.0.0",
  sessionSampleRate: 100,
  sessionReplaySampleRate: 20,
  trackUserInteractions: true,
  trackResources: true,
  trackLongTasks: true,
  defaultPrivacyLevel: "mask-user-input",
});

export function DatadogInit() {
  return null;
}

このコンポーネントを Root Layout に配置します。

// src/app/layout.tsx
import { DatadogInit } from "@/components/DatadogInit";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body>
        <DatadogInit />
        {children}
      </body>
    </html>
  );
}

NPM 方式は TypeScript の型チェックや Tree Shaking の恩恵を受けられます。ただし、React のハイドレーション前に発生したイベントは取得できません。

方式 2: CDN Sync(App Router)

すべてのイベントを取りこぼしなく収集したい場合は、CDN から SDK を同期的にロードする方式を使います。Next.js の Script コンポーネントに strategy="beforeInteractive" を指定することで、ハイドレーション前に SDK がロードされます。

// src/app/layout.tsx
import Script from "next/script";

const DD_APPLICATION_ID = process.env.NEXT_PUBLIC_DD_APPLICATION_ID;
const DD_CLIENT_TOKEN = process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN;
const DD_ENV = process.env.NEXT_PUBLIC_DD_ENV ?? "production";
const DD_VERSION = process.env.NEXT_PUBLIC_DD_VERSION ?? "1.0.0";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body>
        <Script
          src="https://www.datadoghq-browser-agent.com/us1/v6/datadog-rum.js"
          strategy="beforeInteractive"
        />
        <Script id="datadog-rum-init" strategy="beforeInteractive">
          {`
            window.DD_RUM && window.DD_RUM.init({
              applicationId: "${DD_APPLICATION_ID}",
              clientToken: "${DD_CLIENT_TOKEN}",
              site: "datadoghq.com",
              service: "my-nextjs-app",
              env: "${DD_ENV}",
              version: "${DD_VERSION}",
              sessionSampleRate: 100,
              sessionReplaySampleRate: 20,
              trackUserInteractions: true,
              trackResources: true,
              trackLongTasks: true,
              defaultPrivacyLevel: "mask-user-input",
            });
          `}
        </Script>
        {children}
      </body>
    </html>
  );
}

CDN Sync 方式は初期ロードのパフォーマンスデータやエラーをすべて取得できますが、ページロード性能に影響する可能性がある点に注意してください。

Pages Router の場合

Pages Router では _app.tsx のモジュールレベルで SDK を初期化します。

// src/pages/_app.tsx
import type { AppProps } from "next/app";
import { datadogRum } from "@datadog/browser-rum";

datadogRum.init({
  applicationId: process.env.NEXT_PUBLIC_DD_APPLICATION_ID!,
  clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN!,
  site: "datadoghq.com",
  service: "my-nextjs-app",
  env: process.env.NEXT_PUBLIC_DD_ENV ?? "production",
  version: process.env.NEXT_PUBLIC_DD_VERSION ?? "1.0.0",
  sessionSampleRate: 100,
  sessionReplaySampleRate: 20,
  trackUserInteractions: true,
  trackResources: true,
  trackLongTasks: true,
  defaultPrivacyLevel: "mask-user-input",
});

export default function App({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

環境変数の管理

clientToken はシークレットではありません(ブラウザに公開される値です)。applicationId も公開前提の識別子ですが、環境ごとに異なる値を使うため、環境変数で管理するのが一般的です。

Next.js では NEXT_PUBLIC_ プレフィックスを付けた環境変数がブラウザに公開されます。

# .env.local (Next.js)
NEXT_PUBLIC_DD_APPLICATION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
NEXT_PUBLIC_DD_CLIENT_TOKEN=pubxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_DD_ENV=production
NEXT_PUBLIC_DD_VERSION=1.0.0

Vite の場合は VITE_ プレフィックスを使います。

# .env (Vite)
VITE_DD_APPLICATION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
VITE_DD_CLIENT_TOKEN=pubxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
VITE_DD_ENV=production
VITE_DD_VERSION=1.0.0

RUM ダッシュボードの見方

RUM SDK を導入すると、Datadog コンソールの Digital Experience > Performance Summary にデータが表示されます。ここでは、最初に確認すべきポイントを紹介します。

Overview ダッシュボード

Overview ダッシュボードでは、アプリケーション全体の健全性を一目で確認できます。

  • Core Web Vitals — LCP(Largest Contentful Paint)、INP(Interaction to Next Paint)、CLS(Cumulative Layout Shift)のスコア。Google が定義するパフォーマンス指標で、SEO にも影響する(INP の計測には RUM Browser SDK v5.1.0 以降が必要)
  • Loading Time — ページの読み込み時間の分布。P50、P75、P99 などのパーセンタイルで確認する
  • Error Rate — JavaScript エラーの発生率。デプロイ後に急増していないかを確認する

Performance ビュー

Performance ビューでは、ページごとのパフォーマンスを詳細に分析できます。

  • ページ(View)ごとの読み込み時間を比較し、ボトルネックとなっているページを特定する
  • Waterfall チャートで、各リソースの読み込み順序と所要時間を可視化する
  • Long Tasks の発生箇所を特定し、メインスレッドのブロッキングを改善する

Error Tracking

Error Tracking では、エラーをグループ化して管理できます。

  • 同じスタックトレースのエラーを自動的にグループ化する
  • エラーごとの影響を受けたセッション数を確認できる
  • エラー発生時のユーザーの操作履歴(Action)を遡ることで、再現手順を把握できる

まとめ

この記事では、Datadog RUM の概要と導入方法をまとめました。

  • RUM は実際のユーザーのブラウザからパフォーマンスデータを収集する手法で、Synthetic Monitoring とは補完的な関係にある
  • Datadog RUM SDK を React や Next.js に導入することで、Core Web Vitals、エラー、ユーザー操作などのデータを自動収集できる
  • React SPA では init() をモジュールレベルで呼ぶことで、初期ロードからデータを計測できる
  • Next.js では NPM(Client Component)と CDN Sync(beforeInteractive)の 2 つの方式があり、イベント収集の網羅性とパフォーマンス影響のトレードオフで選択する
  • RUM ダッシュボードの Overview、Performance、Error Tracking を活用することで、ユーザー体験の全体像を把握できる

RUM を導入したら、まずは Overview ダッシュボードで Core Web Vitals とエラー率を定期的に確認するところから始めるのがおすすめです。

参考

※ Datadog は Datadog, Inc. の商標です。

ABOUT ME
ぴょい
ぴょい
しがないソフトウェアエンジニアです。 学んだことをメモがわりに書いています。たまに技術以外の話も。 このブログの内容は個人の見解であり、所属組織とは関係ありません。記載内容には誤りがある可能性がありますので、公式ドキュメント等もあわせてご確認ください。
記事URLをコピーしました