关于 applicationinsights-web-ts
这项 TypeScript 技能介绍如何为浏览器应用和 React Native 添加 Application Insights 用户监测,涵盖遥测、分布式追踪、框架插件,以及可关联后端跨度的 GenAI 追踪。
主要功能
- 01采集页面浏览和依赖数据
- 02跟踪异常、事件和指标
- 03监测 SPA 路由和点击
- 04关联前端与后端追踪
- 05按 OTel 规范记录 GenAI 追踪
- 06配置隐私和采样
适用场景
- 01监测浏览器应用的使用情况和错误
- 02跨前端与后端追踪请求
- 03衡量 GenAI Agent 和工具活动
- 04为 React 或 Angular 应用添加遥测
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ skills --skill applicationinsights-web-ts安装后在 Claude Code 中输入/applicationinsights-web-ts确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/agent-traces.mdconfiguration.mdframework-extensions.md详细介绍
TypeScript 的 Application Insights JavaScript SDK(Web)
使用 @microsoft/applicationinsights-web 为浏览器应用提供真实用户监控(RUM)。自动收集页面浏览、AJAX/fetch 依赖项、未处理的异常,以及(使用 Click Analytics 插件时)点击数据。支持自定义事件、指标和生成式 AI Agent 跟踪,遵循 OpenTelemetry GenAI 语义约定,并通过 W3C Trace Context 与后端 Span 关联。
与
azure-monitor-opentelemetry-ts不同,后者用于 Node.js 服务端应用。本技能适用于浏览器/Web 代码(以及 React Native)。
实施前
在 microsoft-docs MCP 中搜索最新的 API 用法:
- 查询:“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-js | React 插件(路由器检测、Hook、HOC、ErrorBoundary)。 |
@microsoft/applicationinsights-react-native | React Native 插件(原生崩溃、会话)。 |
@microsoft/applicationinsights-angularplugin-js | Angular 插件(路由器事件、ErrorHandler)。 |
@microsoft/applicationinsights-debugplugin-js | 仅供开发使用的遥测检查器。 |
@microsoft/applicationinsights-perfmarkmeasure-js | User 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");
}
});
点击分析
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的withAITrackingHOC(参见 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 Agent 跟踪(OTel 语义约定)
当浏览器调用 AI Agent(函数调用、工具使用、直接从客户端发起模型调用)时,发送 App Insights Dependency 遥测数据,其属性遵循 OpenTelemetry GenAI 语义约定,以便在 App Insights / Log Analytics 中与后端 Agent 跨度一起查询。
先设置选择启用的环境变量,确保后端插桩使用相同的架构版本:
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 / Agent 后端跨度会归属到 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()。
常见问题
- 不要重复初始化。 在不同的打包中重新导入模块会产生重复的页面浏览记录。请使用单一的共享模块导出。
- 在用户首次输入前初始化,以免丢失早期的点击或异常。
- 连接字符串是公开的——切勿将同一个 App Insights 资源用于后端机密。
enableAutoRouteTracking+ 手动trackPageView= 重复记录。二选一。- CORS 分布式追踪要求 API 允许
Request-Id、Request-Context、traceparent、tracestate请求标头,并公开Request-Context响应标头。 - GenAI 敏感内容(
gen_ai.input.messages等)默认选择不启用——未经明确的运行时标记和批准的数据处理,切勿记录。 - Agent 的令牌用量记录在
chatspan 上,而不是invoke_agent上——只有在确认用量后,才将汇总用量复制到父级 Agent span。 - React StrictMode 会在开发环境中双重调用副作用——使用模块级单例保护
loadAppInsights()。
包体积
完整的 Web SDK 压缩后约为 110 KB(gzip 后约为 36 KB)。若要严格控制体积预算,请使用 Loader Script 路径,让 SDK 异步加载,避免占用关键路径;或者通过 tree-shaking 移除未使用的插件。
关键类型
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";
最佳实践
- 从单个模块导出一个单例实例。
- 在应用入口点尽早初始化,并在路由器设置之前完成。
- 使用遥测初始化器附加
app.version、tenantId,并清除 PII / 查询字符串机密信息。 - 设置
distributedTracingMode: 2,并确保 API 接受并公开 W3C 追踪上下文标头。 - 对于 GenAI,请逐字遵循 OTel
gen_ai.*属性名称,以便在浏览器和后端遥测中统一查询。 - 通过构建时或运行时选择启用来控制敏感内容采集(
gen_ai.input.messages/gen_ai.output.messages)。 - 在注销或敏感导航时刷新,以免丢弃正在传输的遥测数据。
参考资料
- references/agent-traces.md — 完整梳理 OTel GenAI 语义约定(Agent / 模型 / 工具 span、属性、内容采集)。
- references/framework-extensions.md — React、React Native、Angular、Next.js、Vite 配方。
- references/configuration.md — 完整的
IConfiguration参考和调优指南。 - Microsoft Learn:https://learn.microsoft.com/azure/azure-monitor/app/javascript-sdk
- ApplicationInsights-JS 源码:https://github.com/microsoft/ApplicationInsights-JS
- OTel GenAI 语义约定:https://opentelemetry.io/docs/specs/semconv/gen-ai/