mcpField
A
applicationinsights-web-ts

applicationinsights-web-ts

github.com/microsoft開発3.2k39 回インストール今日更新
リポジトリ

applicationinsights-web-ts について

ブラウザーアプリと React Native に Application Insights のリアルユーザーモニタリングを導入する TypeScript スキルです。テレメトリー、分散トレース、フレームワーク用プラグインに加え、バックエンドのスパンと関連付ける GenAI トレースを扱います。

主な機能

  1. 01ページビューと依存関係を収集
  2. 02例外、イベント、メトリクスを記録
  3. 03SPA のルートとクリックを計測
  4. 04フロントエンドとバックエンドのトレースを関連付け
  5. 05OTel 規約に沿った GenAI トレース
  6. 06プライバシーとサンプリングを設定

活用シーン

  1. 01ブラウザーアプリの利用状況とエラーを監視
  2. 02フロントエンドからバックエンドまでリクエストを追跡
  3. 03GenAI エージェントとツールの動作を計測
  4. 04React または Angular アプリにテレメトリーを追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/microsoft/skills --skill applicationinsights-web-ts

インストール後、Claude Code で/applicationinsights-web-tsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
agent-traces.md
configuration.md
framework-extensions.md

詳細

TypeScript 向け Application Insights JavaScript SDK(Web)

@microsoft/applicationinsights-web を使用して、ブラウザーアプリのリアルユーザー監視(RUM)を行います。ページビュー、AJAX/fetch の依存関係、未処理の例外を自動収集し、Click Analytics プラグインを使用するとクリックも収集します。カスタムイベントやメトリックに加え、OpenTelemetry GenAI のセマンティック規約に準拠し、W3C Trace Context を介してバックエンドのスパンと関連付ける GenAI エージェントのトレース にも対応しています。

azure-monitor-opentelemetry-ts とは異なります。こちらは Node.js サーバーアプリ向けです。このスキルは ブラウザー/Web コード(および React Native)向けです。

実装前

最新の API パターンを microsoft-docs MCP で検索します。

  • クエリ:"Application Insights JavaScript SDK setup"
  • クエリ:"Application Insights JavaScript SDK configuration"
  • クエリ:"Application Insights JavaScript framework extensions React Angular"
  • パッケージのバージョンを確認します:npm view @microsoft/applicationinsights-web version

パッケージ

パッケージ用途
@microsoft/applicationinsights-webコア RUM SDK(ページビュー、AJAX、例外)。
@microsoft/applicationinsights-clickanalytics-jsクリックのテレメトリを自動収集します。
@microsoft/applicationinsights-react-jsReact プラグイン(ルーターの計装、フック、HOC、ErrorBoundary)。
@microsoft/applicationinsights-react-nativeReact Native プラグイン(ネイティブのクラッシュ、セッション)。
@microsoft/applicationinsights-angularplugin-jsAngular プラグイン(ルーターイベント、ErrorHandler)。
@microsoft/applicationinsights-debugplugin-js開発専用のテレメトリインスペクター。
@microsoft/applicationinsights-perfmarkmeasure-jsUser Timing(performance.mark/measure)との統合。

インストール

npm i --save @microsoft/applicationinsights-web
# Optional plugins (install only what you use):
npm i --save @microsoft/applicationinsights-clickanalytics-js
npm i --save @microsoft/applicationinsights-react-js @microsoft/applicationinsights-react-native @microsoft/applicationinsights-angularplugin-js

型定義はパッケージに含まれているため、別途 @types/... をインストールする必要はありません。

接続文字列

ブラウザー SDK では、初期化時に接続文字列が必要です。接続文字列はプレーンテキストでクライアントに配布されます。ブラウザーのテレメトリでは Microsoft Entra ID 認証はサポートされていません。バックエンドのテレメトリと分離する必要がある場合は、ブラウザーの RUM 用にローカル認証を有効にした別の App Insights リソースを使用してください。

# Vite / CRA / Next.js — expose to client via the public env prefix
VITE_APPINSIGHTS_CONNECTION_STRING="InstrumentationKey=...;IngestionEndpoint=https://...;LiveEndpoint=https://..."
NEXT_PUBLIC_APPINSIGHTS_CONNECTION_STRING="InstrumentationKey=..."

クイックスタート(npm)

import { ApplicationInsights } from "@microsoft/applicationinsights-web";

export const appInsights = new ApplicationInsights({
  config: {
    connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
    enableAutoRouteTracking: true,        // SPA route changes -> page views
    enableCorsCorrelation: true,          // propagate Request-Id / traceparent to cross-origin AJAX
    enableRequestHeaderTracking: true,
    enableResponseHeaderTracking: true,
    distributedTracingMode: 2,            // DistributedTracingModes.AI_AND_W3C — emit traceparent for backend correlation
    autoTrackPageVisitTime: true,
    disableFetchTracking: false,          // fetch() is auto-instrumented by default
    excludeRequestFromAutoTrackingPatterns: [/livemetrics\.azure\.com/i]
  }
});

appInsights.loadAppInsights();
appInsights.trackPageView();

loadAppInsights() は、追跡対象にしたいユーザー操作より前に、できるだけ早く一度だけ呼び出します。次に、初回読み込みのために trackPageView() を呼び出します。enableAutoRouteTracking が有効な場合、その後のルート変更は自動的に追跡されます。

クイックスタート(SDK ローダースクリプト)

SDK を自動更新し、ビルドパイプラインを使わずに済ませたい場合におすすめです。これを <head> 内の 最初の <script> として貼り付けます。

<script type="text/javascript" src="https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js" crossorigin="anonymous"></script>
<script type="text/javascript">
  var appInsights = window.appInsights || function (cfg) {
    /* See: https://learn.microsoft.com/azure/azure-monitor/app/javascript-sdk
       Use the latest snippet from the Microsoft Learn page above — it includes
       backup-CDN failover (cr), SDK-load-failure reporting, and the queue shim
       so calls before SDK ready are not lost. */
  }({ src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
      crossOrigin: "anonymous",
      cfg: { connectionString: "YOUR_CONNECTION_STRING" } });
</script>

ローダーのみの API(SDK の読み込みが完了するまでキューに登録されます):trackEvent、trackPageView、trackException、trackTrace、trackDependencyData、trackMetric、trackPageViewPerformance、startTrackPage、stopTrackPage、startTrackEvent、stopTrackEvent、addTelemetryInitializer、setAuthenticatedUserContext、clearAuthenticatedUserContext、flush。

コアの追跡 API

// Page views (SPAs that disable enableAutoRouteTracking)
appInsights.trackPageView({ name: "Checkout", uri: "/checkout", properties: { cartSize: 3 } });

// Custom events (user actions, business events)
appInsights.trackEvent({ name: "PurchaseCompleted" }, { orderId: "ord_123", amountUsd: 49.95 });

// Exceptions (caught errors)
try {
  await pay(order);
} catch (err) {
  appInsights.trackException({ exception: err as Error, severityLevel: 3, properties: { orderId: order.id } });
}

// Traces (logs, severity 0=Verbose, 1=Info, 2=Warning, 3=Error, 4=Critical)
appInsights.trackTrace({ message: "Cart hydrated from local storage", severityLevel: 1 });

// Custom metrics (numeric)
appInsights.trackMetric({ name: "checkout.duration_ms", average: 1234 });

// Dependencies (manually-tracked outbound calls — fetch/XHR are auto-tracked)
appInsights.trackDependencyData({
  id: crypto.randomUUID(),
  name: "GET /api/orders",
  duration: 87, success: true, responseCode: 200,
  data: "https://api.example.com/api/orders", target: "api.example.com", type: "Fetch"
});

// User identity (set ONCE per authenticated session — values are PII; do not pass emails)
appInsights.setAuthenticatedUserContext("user-id-123", "tenant-456", /*storeInCookie*/ true);
appInsights.clearAuthenticatedUserContext(); // on logout

// Force send before unload
appInsights.flush();

テレメトリ初期化子(拡充とフィルタリング)

送信前に、すべてのエンベロープに対して実行されます。破棄するには false を返します。

import type { ITelemetryItem } from "@microsoft/applicationinsights-web";

appInsights.addTelemetryInitializer((item: ITelemetryItem) => {
  item.tags ??= {};
  item.tags["ai.cloud.role"] = "web-shop";
  item.tags["ai.cloud.roleInstance"] = window.location.hostname;
  item.data ??= {};
  item.data["app.version"] = import.meta.env.VITE_APP_VERSION;
  item.data["app.build"] = import.meta.env.VITE_BUILD_SHA;

  // Drop noisy health-check page views
  if (item.baseType === "PageviewData" && item.baseData?.uri?.endsWith("/healthz")) return false;

  // Scrub query-string secrets
  if (item.baseData?.uri) {
    item.baseData.uri = item.baseData.uri.replace(/([?&](token|sig|key)=)[^&]+/gi, "$1REDACTED");
  }
});

Click Analytics

import { ClickAnalyticsPlugin } from "@microsoft/applicationinsights-clickanalytics-js";

const clickPlugin = new ClickAnalyticsPlugin();
const appInsights = new ApplicationInsights({
  config: {
    connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
    extensions: [clickPlugin],
    extensionConfig: {
      [clickPlugin.identifier]: {
        autoCapture: true,
        dataTags: { useDefaultContentNameOrId: true, customDataPrefix: "data-ai-" },
        urlCollectHash: false,
        behaviorValidator: (b: string) => /^[a-z0-9_]+$/.test(b) ? b : ""
      }
    }
  }
});
appInsights.loadAppInsights();

要素に data-ai-* 属性を指定します。クリックは、親コンテンツのメタデータを含むカスタムイベントとして出力されます。

SPA のルート追跡

  • 組み込み: enableAutoRouteTracking: true を設定します。history.pushState/replaceState と popstate をフックします。
  • React Router: @microsoft/applicationinsights-react-js の withAITracking HOC を使用します(references/framework-extensions.md を参照)。
  • 手動: ルート変更時に、ルーターの useEffect 内で appInsights.trackPageView({ name, uri }) を呼び出します。二重カウントを避けるには、enableAutoRouteTracking を無効にします。

分散トレーシング(バックエンドとの相関付け)

distributedTracingMode: 2(DistributedTracingModes.AI_AND_W3C)を設定します。SDK は送信する fetch/XHR に traceparent(およびレガシーの Request-Id)を追加します。OpenTelemetry(例:@azure/monitor-opentelemetry)でインストルメント化されたバックエンドは、ブラウザーの operation_Id に自動的にリンクします。

クロスオリジン呼び出しの場合は、enableCorsCorrelation: true も設定し、呼び出し元のオリジンを API の CORS 公開ヘッダーに追加します。

GenAI エージェントのトレース(OTel セマンティック規約)

ブラウザーが AI エージェントを呼び出す場合(関数呼び出し、ツール使用、クライアントから直接行うモデル呼び出し)、属性が OpenTelemetry の GenAI セマンティック規約に従う App Insights の Dependency テレメトリを送信すると、App Insights/Log Analytics でバックエンドのエージェントスパンと併せてクエリできます。

バックエンドのインストルメンテーションが同じスキーマバージョンを使用するよう、最初にオプトイン環境変数を設定します。

OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
必須属性キー(OTel の名称をそのまま使用)
スパン/操作必須属性
invoke_agent {agent.name}gen_ai.operation.name=invoke_agent、gen_ai.provider.name、gen_ai.agent.name、gen_ai.agent.id(判明している場合)
create_agent {agent.name}gen_ai.operation.name=create_agent、gen_ai.provider.name、gen_ai.agent.name、gen_ai.request.model
chat {model}gen_ai.operation.name=chat、gen_ai.provider.name、gen_ai.request.model、gen_ai.response.model、gen_ai.usage.input_tokens、gen_ai.usage.output_tokens
execute_tool {tool.name}gen_ai.operation.name=execute_tool、gen_ai.tool.name、gen_ai.tool.type(function | extension | datastore)、gen_ai.tool.call.id

gen_ai.provider.name の既知の値:openai、azure.ai.openai、azure.ai.inference、anthropic、aws.bedrock、gcp.gemini、gcp.vertex_ai、cohere、mistral_ai、groq、deepseek、perplexity、x_ai、ibm.watsonx.ai。

機密コンテンツのオプトイン。 gen_ai.system_instructions、gen_ai.input.messages、gen_ai.output.messages、gen_ai.tool.call.arguments、gen_ai.tool.call.result は、デフォルトで オプトインです。実行時フラグで制御し、承認されたデータ取り扱い手順がない限り、本番環境では使用しないでください。

パターン:invoke_agent とネストされたツール/モデルスパン
import { ApplicationInsights, SeverityLevel } from "@microsoft/applicationinsights-web";

type GenAiAttrs = Record<string, string | number | boolean | undefined>;

function startGenAiSpan(name: string, attrs: GenAiAttrs) {
  const id = crypto.randomUUID();
  const start = performance.now();
  const baseProps: GenAiAttrs = { "gen_ai.span.id": id, ...attrs };
  return {
    end(success: boolean, extra: GenAiAttrs = {}, error?: Error) {
      const duration = Math.round(performance.now() - start);
      const properties = { ...baseProps, ...extra };
      appInsights.trackDependencyData({
        id, name, duration, success,
        responseCode: error ? 500 : 200,
        type: "GenAI",
        target: String(attrs["gen_ai.provider.name"] ?? "genai"),
        properties: properties as Record<string, string>
      });
      if (error) {
        appInsights.trackException({
          exception: error,
          severityLevel: SeverityLevel.Error,
          properties: { ...properties, "error.type": error.name } as Record<string, string>
        });
      }
    }
  };
}

// Agent invocation
const agentSpan = startGenAiSpan("invoke_agent ResearchAssistant", {
  "gen_ai.operation.name": "invoke_agent",
  "gen_ai.provider.name": "azure.ai.openai",
  "gen_ai.agent.name": "ResearchAssistant",
  "gen_ai.agent.id": "asst_5j66UpCpwteGg4YSxUnt7lPY",
  "gen_ai.request.model": "gpt-4o-mini",
  "server.address": "myresource.openai.azure.com"
});

try {
  // Nested chat completion span
  const chat = startGenAiSpan("chat gpt-4o-mini", {
    "gen_ai.operation.name": "chat",
    "gen_ai.provider.name": "azure.ai.openai",
    "gen_ai.request.model": "gpt-4o-mini"
  });
  const res = await callAzureOpenAi(/* ... */);
  chat.end(true, {
    "gen_ai.response.model": res.model,
    "gen_ai.response.id": res.id,
    "gen_ai.response.finish_reasons": JSON.stringify(res.choices.map(c => c.finish_reason)),
    "gen_ai.usage.input_tokens": res.usage.prompt_tokens,
    "gen_ai.usage.output_tokens": res.usage.completion_tokens,
    "gen_ai.output.type": "text"
  });

  // Nested tool execution span
  const tool = startGenAiSpan("execute_tool getWeather", {
    "gen_ai.operation.name": "execute_tool",
    "gen_ai.tool.name": "getWeather",
    "gen_ai.tool.type": "function",
    "gen_ai.tool.call.id": "call_abc123"
  });
  const toolResult = await runGetWeather({ location: "SF" });
  tool.end(true);

  agentSpan.end(true, {
    "gen_ai.usage.input_tokens": res.usage.prompt_tokens,
    "gen_ai.usage.output_tokens": res.usage.completion_tokens
  });
} catch (err) {
  agentSpan.end(false, { "error.type": (err as Error).name }, err as Error);
}

ブラウザーの traceparent は送信する fetch に自動的に付加されるため(distributedTracingMode: 2 の場合)、下流の Azure OpenAI/エージェントバックエンドのスパンは、App Insights で同じ operation_Id の配下に記録されます。

属性の完全なリファレンス、既知の値、コンテンツ収集のガイダンスについては、references/agent-traces.md を参照してください。

KQL:App Insights で GenAI トレースをクエリする
dependencies
| where type == "GenAI"
| extend op   = tostring(customDimensions["gen_ai.operation.name"]),
         agent = tostring(customDimensions["gen_ai.agent.name"]),
         model = tostring(customDimensions["gen_ai.request.model"]),
         tin   = toint(customDimensions["gen_ai.usage.input_tokens"]),
         tout  = toint(customDimensions["gen_ai.usage.output_tokens"])
| summarize calls=count(), p95_ms=percentile(duration, 95),
            avg_in=avg(tin), avg_out=avg(tout) by op, agent, model, bin(timestamp, 5m)

React(TypeScript)

React、React Native、Angular、Next.js、Vite の詳しいレシピについては、references/framework-extensions.md を参照してください。

import { ApplicationInsights } from "@microsoft/applicationinsights-web";
import { ReactPlugin, withAITracking } from "@microsoft/applicationinsights-react-js";
import { createBrowserHistory } from "history";

const reactPlugin = new ReactPlugin();
const browserHistory = createBrowserHistory();

export const appInsights = new ApplicationInsights({
  config: {
    connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
    extensions: [reactPlugin],
    extensionConfig: { [reactPlugin.identifier]: { history: browserHistory } }
  }
});
appInsights.loadAppInsights();

export const TrackedCheckout = withAITracking(reactPlugin, Checkout, "Checkout");

React Native

import { ApplicationInsights } from "@microsoft/applicationinsights-web";
import { ReactNativePlugin } from "@microsoft/applicationinsights-react-native";

const rnPlugin = new ReactNativePlugin();
const appInsights = new ApplicationInsights({
  config: {
    connectionString: process.env.EXPO_PUBLIC_APPINSIGHTS_CONNECTION_STRING,
    extensions: [rnPlugin],
    disableFetchTracking: false
  }
});
appInsights.loadAppInsights();

パフォーマンス — Web Vitals

自動収集:PerformanceTiming/PerformanceNavigationTiming によるページ読み込み時間。Core Web Vitals を追加するには:

import { onCLS, onLCP, onINP, type Metric } from "web-vitals";

function send(m: Metric) {
  appInsights.trackMetric(
    { name: `web_vitals.${m.name.toLowerCase()}`, average: m.value },
    { rating: m.rating, navigationType: m.navigationType, id: m.id }
  );
}
onCLS(send); onLCP(send); onINP(send);

Cookie とプライバシー

new ApplicationInsights({ config: {
  connectionString,
  isCookieUseDisabled: true,         // hard-disable all cookies
  cookieCfg: { enabled: true, domain: ".example.com", path: "/", expiry: 365 }
}});

同意状態を動的に反映するには:

appInsights.getCookieMgr().setEnabled(userGaveConsent);
appInsights.config.disableTelemetry = !userGaveConsent;

サンプリング

サーバー側の取り込みサンプリング(推奨)は、App Insights リソースで設定します。SDK 側のサンプリングにより、ネットワーク使用量を削減できます。

new ApplicationInsights({ config: { connectionString, samplingPercentage: 50 } });

テレメトリ初期化子によるタイプ別サンプリング:item.baseType に基づいて return false を返し、破棄します。

オフライン/送信時のフラッシュ

SDK は sendBeacon(デフォルトは onunloadDisableBeacon: false)を使用して、pagehide/unload 時にデータをフラッシュします。SPA では、破壊的な遷移(ログアウト、ハードリロード)の前にも appInsights.flush() を呼び出してください。

よくある落とし穴

  1. 二重に初期化しないでください。 異なるバンドルでモジュールを再インポートすると、ページビューが重複します。共有モジュールのエクスポートは1つだけ使用してください。
  2. 最初のユーザー入力より前に初期化してください。 そうしないと、初期のクリックや例外が失われる可能性があります。
  3. 接続文字列は公開情報です — バックエンドのシークレットには、同じ App Insights リソースを決して再利用しないでください。
  4. enableAutoRouteTracking と手動の trackPageView を併用すると重複します。どちらか一方を選んでください。
  5. CORS の分散トレース を利用するには、API で Request-Id、Request-Context、traceparent、tracestate のリクエストヘッダーを許可し、Request-Context レスポンスヘッダーを公開する必要があります。
  6. GenAI の機密コンテンツ(gen_ai.input.messages など)はオプトインです。明示的なランタイムフラグと承認済みのデータ取り扱いがない限り、決してログに記録しないでください。
  7. エージェントのトークン使用量は invoke_agent ではなく chat スパンに記録されます — 使用量を把握している場合に限り、集計した使用量を親のエージェントスパンにコピーしてください。
  8. React StrictMode では開発時にエフェクトが二重に呼び出されます。loadAppInsights() をモジュールレベルのシングルトンで保護してください。

バンドルサイズ

Web SDK のフル版は、最小化後で約 110 KB(gzip 圧縮後で約 36 KB)です。サイズの制約が厳しい場合は、クリティカルパス外で SDK を非同期に読み込める Loader Script の方法を使用するか、未使用のプラグインをツリーシェイクしてください。

主な型

import {
  ApplicationInsights,
  SeverityLevel,
  DistributedTracingModes,
  type IConfiguration,
  type IConfig,
  type ITelemetryItem,
  type ITelemetryPlugin,
  type ICustomProperties,
  type IPageViewTelemetry,
  type IEventTelemetry,
  type IExceptionTelemetry,
  type ITraceTelemetry,
  type IMetricTelemetry,
  type IDependencyTelemetry
} from "@microsoft/applicationinsights-web";

ベストプラクティス

  1. シングルトンインスタンスを1つだけにする — 1つのモジュールからエクスポートしてください。
  2. 早い段階で初期化する — ルーターを設定する前に、アプリのエントリーポイントで初期化してください。
  3. テレメトリ初期化子を使用する — app.version、tenantId を付加し、PII やクエリー文字列のシークレットを除去してください。
  4. distributedTracingMode: 2 を設定する — API が W3C トレースコンテキストのヘッダーを受け入れ、公開することを確認してください。
  5. GenAI では、OTel の gen_ai.* 属性名をそのまま使用してください。ブラウザーとバックエンドのテレメトリ全体で一貫してクエリーできます。
  6. 機密コンテンツの取得(gen_ai.input.messages / gen_ai.output.messages)は、ビルド時またはランタイムのオプトインを条件にしてください。
  7. ログアウト時や機密性の高い画面への移動時にフラッシュする — 送信中のテレメトリが破棄されないようにしてください。

参考資料

コメント