Application Insights Web TypeScript
用于 TypeScript 的 Application Insights JavaScript SDK (Web)
使用场景
当你需要使用 Application Insights JavaScript SDK (@microsoft/applicationinsights-web) 对浏览器/Web 应用进行插桩时,请使用此技能。适用于真实用户监控 (RUM) —— 包括页面浏览量、点击、AJAX/fetch 依赖、异常、自定义事件,以及与后端关联的浏览器端 GenAI 代理追踪...
通过 @microsoft/applicationinsights-web 实现浏览器应用的真实用户监控 (RUM)。自动收集页面浏览量、AJAX/fetch 依赖、未处理的异常,以及(配合 Click Analytics 插件)点击事件。支持自定义事件、指标以及遵循 OpenTelemetry GenAI 语义约定并通过 W3C Trace Context 与后端 Span 关联的 GenAI 代理追踪。
> 与 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 插件(路由插桩、hooks、HOC、ErrorBoundary)。 |
| @microsoft/applicationinsights-react-native | React Native 插件(原生崩溃、会话)。 |
| @microsoft/applicationinsights-angularplugin-js | Angular 插件(路由事件、ErrorHandler)。 |
| @microsoft/applicationinsights-debugplugin-js | 仅限开发环境的遥测检查器。 |
| @microsoft/applicationinsights-perfmarkmeasure-js | 用户计时 (performance.mark/measure) 集成。 |
安装
npm i --save @microsoft/applicationinsights-web
可选插件(仅安装所需的):
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 — 通过公共环境变量前缀暴露给客户端
VITE_APPINSIGHTS_CONNECTION_STRING="InstrumentationKey=...;IngestionEnd## 快速上手 (npm)export const appInsights = new ApplicationInsights({
config: {
connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
enableAutoRouteTracking: true, // SPA 路由变更 -> 页面浏览量
enableCorsCorrelation: true, // 将 Request-Id / traceparent 传递给跨域 AJAX
enableRequestHeaderTracking: true,
enableResponseHeaderTracking: true,
distributedTracingMode: 2, // DistributedTracingModes.AI_AND_W3C — 发送 traceparent 以进行后端关联
autoTrackPageVisitTime: true,
disableFetchTracking: false, // 默认自动监测 fetch()
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) {
/* 详见: https://learn.microsoft.com/azure/azure-monitor/app/javascript-sdk
请使用上述 Microsoft Learn 页面上的最新代码片段 —— 它包含了
备份 CDN 故障转移 (cr)、SDK 加载失败报告以及队列垫片 (queue shim),
以确保在 SDK 就绪之前的调用不会丢失。 */
}({ 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
// 自定义事件 (用户操作、业务事件)
appInsights.trackEvent({ name: "PurchaseCompleted" }, { orderId: "ord_123", amountUsd: 49.95 });
// 异常 (捕获的错误)
try {
await pay(order);
} catch (err) {
appInsights.trackException({ exception: err as Error, severityLevel: 3, properties: { orderId: order.id } });
}
// 跟踪日志 (级别 0=详细, 1=信息, 2=警告, 3=错误, 4=严重)
appInsights.trackTrace({ message: "Cart hydrated from local storage", severityLevel: 1 });
// 自定义指标 (数值)
appInsights.trackMetric({ name: "checkout.duration_ms", average: 1234 });
// 依赖项 (手动追踪的出站调用 —— fetch/XHR 已自动追踪)
appInsights.trackDependencyData({
id: crypto.randomUUID(),
name: "GET /api/orders",
duration: 87, success: true, responseCode: 200,
data: "https://api.example.com/api/orders", tar
get: "api.example.com", type: "Fetch"
});
// 用户身份(每个认证会话仅设置一次 —— 值为 PII;请勿传递电子邮件)
appInsights.setAuthenticatedUserContext("user-id-123", "tenant-456", /*storeInCookie*/ true);
appInsights.clearAuthenticatedUserContext(); // 登出时调用
// 在卸载前强制发送
appInsights.flush();
遥测初始化程序 (Telemetry Initializers)(增强与过滤)
在发送每个信封 (envelope) 之前运行。返回 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_APP_BUILD_SHA;
// 丢弃嘈杂的健康检查页面浏览量
if (item.baseType === "PageviewData" && item.baseData?.uri?.endsWith("/healthz")) return false;
// 清洗查询字符串中的机密信息
if (item.baseData?.uri) {
item.baseData.uri = item.baseData.uri.replace(/(?&=)[^&]+/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-* 属性标记元素;点击事件将作为带有父级内容元数据的自定义事件 (Custom Events) 发出。
SPA 路由跟踪
- 内置: 设置
enableAutoRouteTracking: true。它会挂钩history.pushState/replaceState和popstate。
- React Router: 使用
@microsoft/applicationinsights-react-js的withAITrackingHOC(参见 references/framework-extensions.md)。
- 手动: 在路由器的
useEffect中于路由更改时调用appInsights.trackPageView({ name, uri })。禁用enableAutoRouteTracking以避免重复计数。
分布式追踪 (Distributed Tracing)(与后端关联)
设置 distributedTracingMode: 2 (DistributedTracingModes.AI_AND_W3C)。SDK 会在发出的 fetch/XHR 请求中添加 traceparent(以及旧版的 Request-Id)。使用 OpenTelemetry(例如 @azure/monitor-opentelemetry)进行插桩的后端会自动链接到浏览器的 operation_Id。
对于跨域调用,还需设置 enableCorsCorrelation: true,并在 API 的 CORS 暴露头 (exposed headers) 中添加调用源。
GenAI Agent 追踪 (OTel 语义约定)
当浏览器调用 AI Agent(函数调用、工具使用、直接从客户端调用模型)时,发出符合 OpenTelemetry GenAI 语义约定 的 App Insights Dependency 遥测,以便在 App Insights / Log Analytics 中与后端 Agent 的 span 一起进行查询。
设置选择性加入的端...
首先,请确保后端 instrumentation 统一使用相同的 schema 版本:
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental必需的属性键(请原样使用 OTel 名称)
| Span / 操作 | 必需属性 |
| --- | --- |
| 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 默认是 Opt-In(需手动启用) 的。请通过运行时标志(runtime flag)进行控制,除非已通过数据处理审核,否则请避免在生产环境中使用。
模式:invoke_agent + 嵌套的 tool/model spans
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 调用
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 {
// 嵌套的聊天补全 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_token
s": res.usage.completion_tokens,
"gen_ai.output.type": "text"
});
// 嵌套工具执行 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 后端 span 将在 App Insights 中挂在同一个 operation_Id 之下。
有关完整的属性参考、常用值和内容捕获指南,请参阅 references/agent-traces.md。
KQL:在 App Insights 中查询 GenAI 追踪
## 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 Nativeimport { 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, // 强制禁用所有 Cookie
cookieCfg: { enabled: true, domain: ".example.com", path: "/", expiry: 365 }
}});动态处理用户同意:
appInsights.getCookieMgr().setEnabled(userGaveConsent);
appInsights.config.disableTelemetry = !userGaveConsent;采样 (Sampling)
服务端接收采样(推荐)在 App Insights 资源中配置。SDK 端采样可减少网络带宽占用:
new ApplicationInsights({ config: { connectionString, samplingPercentage: 50 } });可通过遥测初始化程序 (telemetry initializer) 实现分类型采样:根据 item.baseType 返回 false 以丢弃数据。
离线 / 卸载时发送
SDK 使用 sendBeacon(默认 onunloadDisableBeacon: false)在 pagehide / unload 时刷新数据。对于单页应用 (SPA),在执行破坏性跳转(如登出、强制刷新)前,请调用 appInsights.flush()。
常见陷阱
1. 避免重复初始化:在不同 bundle 中重复导入模块会导致页面浏览量 (page views) 重复统计。请使用统一的共享模块导出。
2. 在首次用户输入前初始化:避免丢失早期的点击或异常记录。
3. 连接字符串是公开的:切勿将同一个 App Insights 资源用于存储后端机密。
4. enableAutoRouteTracking 与手动 trackPageView 共存:会导致重复统计。请二选一。
5. CORS 分布式追踪:要求 API 允许 Request-Id、Request-Context、traceparent、tracestate 请求头,并公开 Request-Context 响应头。
6. GenAI 敏感内容(如 gen_ai.input.messages 等)采用 Opt-In 机制:在没有明确的运行时标志和经批准的数据处理流程前,请勿记录。
7. Agent Token 使用量记录在 chat span 而非 invoke_agent:仅在确定时才将聚合使用量复制到父级 agent span。
8. React StrictMode:在开发环境下会双次调用 effect —— 请使用模块级单例来保护 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";最佳实践
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 的捕获置于构建时或运行时的 Opt-in 标志之后。
7. 在登出/敏感导航时刷新:确保在途的遥测数据不会丢失。
参考资料
- [agent-traces.md — 完整的 OTel GenAI 语义约定精简版(包含 agent / model / tool 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/>
局限性
- 仅在任务与上游源码及本地项目上下文明确匹配时使用此技能。
- 在应用更改前,请验证命令、生成的代码、依赖项、凭据以及外部服务的行为。
- 不要将示例视为环境特定测试、安全审查或破坏性/高成本操作用户确认的替代方案。