applicationinsights-web-ts
microsoft/skills
Application Insights JavaScript SDK for Real User Monitoring(RUM)을 사용하여 페이지 조회, 클릭, AJAX/fetch 종속성, 예외, 사용자 정의 이벤트 및 백엔드 OpenTelemetry 추적 정보와 연관된 GenAI 에이전트 추적 정보를 포함한 브라우저/웹 앱을 모니터링할 수 있습니다.
...모든 것을 확장하십시오TypeScript용 Application Insights JavaScript SDK (웹)
브라우저 앱용 실제 사용자 모니터링(RUM) @microsoft/applicationinsights-web. 페이지 뷰, AJAX/fetch 종속성, 처리되지 않은 예외 및 (클릭 분석 플러그인 사용 시) 클릭 정보를 자동으로 수집합니다. OpenTelemetry GenAI 의미론적 규칙을 따르며 W3C Trace Context를 통해 백엔드 스팬과 연관되는 사용자 지정 이벤트, 메트릭 및 GenAI 에이전트 추적을 지원합니다.
Node.js 서버 앱용인
azure-monitor-opentelemetry-ts와는 다릅니다. 이 스킬은 브라우저/웹 코드(및 React Native)용입니다.
구현 전
검색 microsoft-docs MCP에서 최신 API 패턴을 검색하세요:
- 쿼리: "Application Insights JavaScript SDK 설정"
- 쿼리: "Application Insights JavaScript SDK 구성"
- 쿼리: "Application Insights JavaScript 프레임워크 확장 기능 React Angular"
- 패키지 버전 확인:
npm view @microsoft/applicationinsights-web version
패키지
| 패키지 | 용도 |
|---|---|
@microsoft/applicationinsights-web |
핵심 RUM SDK(페이지 뷰, AJAX, 예외). |
@microsoft/applicationinsights-clickanalytics-js |
클릭 텔레메트리 자동 수집. |
@microsoft/applicationinsights-react-js |
React 플러그인(라우터 계측, 훅, 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
타이핑(Typings)은 패키지에 포함되어 있으므로 별도의 @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를 자동으로 업데이트하고 빌드 파이프라인을 전혀 사용하지 않으려는 경우 권장합니다. 다음 코드를 첫 번째로 붙여넣으십시오. in :
로더 전용 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-jswithAITrackingHOC 사용 (references/framework-extensions.md 참조). - 수동: 호출
appInsights.trackPageView({ name, uri })라우터 내에서useEffect경로 변경 시 호출하십시오. 중복 계산을 방지하기 위해enableAutoRouteTracking중복 계산을 방지합니다.
분산 추적 (백엔드와 상관관계 분석)
설정 distributedTracingMode: 2 (DistributedTracingModes.AI_AND_W3C). SDK는 traceparent (및 레거시 Request-Id)를 아웃바운드 fetch/XHR. OpenTelemetry로 계측된 백엔드(예: @azure/monitor-opentelemetry)로 계측된 백엔드는 브라우저의 operation_Id에 자동으로 연결됩니다.
크로스 오리진 호출의 경우, 다음을 설정하고 enableCorsCorrelation: true 설정하고, 호출 원본을 API의 CORS 노출 헤더에 추가해야 합니다.
GenAI 에이전트 트레이스(OTel 의미론적 규칙)
브라우저가 AI 에이전트를 호출할 때(함수 호출, 도구 사용, 클라이언트에서 직접 모델 호출 등), App Insights / Log Analytics에서 백엔드 에이전트 스팬과 함께 쿼리할 수 있도록 OpenTelemetry GenAI 의미론적 규칙을 따르는 속성을 가진 App Insights 종속성 텔레메트리 데이터를 생성합니다.
백엔드 계측이 동일한 스키마 버전을 사용하도록 먼저 옵트인 환경 변수를 설정하십시오:
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
필수 속성 키(OTel 이름을 그대로 사용)
| 스팬 / op | 필수 속성 |
|---|---|
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) 상태입니다. 런타임 플래그를 통해 접근을 제한하고, 데이터 처리가 승인된 경우가 아니라면 프로덕션 환경에서는 이를 사용하지 마십시오.
패턴: invoke_agent + 중첩된 도구/모델 스팬
import { ApplicationInsights, SeverityLevel } from "@microsoft/applicationinsights-web";
type GenAiAttrs = Record;
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
});
if (error) {
appInsights.trackException({
exception: error,
severityLevel: SeverityLevel.Error,
properties: { ...properties, "error.type": error.name } as Record
});
}
}
};
}
// 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);
쿠키 및 개인정보 보호
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 } });
텔레메트리 초기화기를 통한 유형별 샘플링: return false 다음에 따라 item.baseType.
오프라인 / 언로드 시 전송
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등)은 옵트인 방식입니다. 명시적인 런타임 플래그와 승인된 데이터 처리 절차 없이는 절대 기록하지 마십시오. - 에이전트 토큰 사용량은
chat스팬에서 확인되며,invoke_agent에서는 확인할 수 없습니다. 사용량을 알고 있는 경우에만 집계된 사용량을 상위 에이전트 스팬으로 복사하십시오. - React StrictMode는 개발 환경에서 이펙트를 두 번 호출합니다 —
loadAppInsights()모듈 수준의 싱글톤으로 보호하십시오.
번들 크기
전체 웹 SDK는 gzip 압축 시 최소화된 크기 110KB (36KB입니다). 예산이 매우 제한적인 경우, 로더 스크립트 경로를 사용하여 SDK가 중요 경로에서 비동기적으로 로드되도록 하거나, 사용되지 않는 플러그인을 트리 쉐이크하십시오.
키 유형
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 semconv의 전체 내용 요약 (에이전트/모델/도구 스팬, 속성, 콘텐츠 캡처).
- 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/
---
name: applicationinsights-web-ts
description: Instrument browser/web apps with the Application Insights JavaScript SDK for Real User Monitoring (RUM), including page views, clicks, AJAX/fetch dependencies, exceptions, custom events, and GenAI agent traces correlated to backend OpenTelemetry traces.
license: MIT
---
# Application Insights JavaScript SDK (Web) for TypeScript
Real User Monitoring (RUM) for browser apps with `@microsoft/applicationinsights-web`. Auto-collects page views, AJAX/fetch dependencies, unhandled exceptions, and (with the Click Analytics plugin) clicks. Supports custom events, metrics, and **GenAI agent traces** that follow OpenTelemetry GenAI semantic conventions and correlate to backend spans via W3C Trace Context.
> **Distinct from `azure-monitor-opentelemetry-ts`**, which is for Node.js server apps. This skill is for **browser/web** code (and React Native).
## Before Implementation
Search `microsoft-docs` MCP for current API patterns:
- Query: "Application Insights JavaScript SDK setup"
- Query: "Application Insights JavaScript SDK configuration"
- Query: "Application Insights JavaScript framework extensions React Angular"
- Verify package version: `npm view @microsoft/applicationinsights-web version`
## Packages
| Package | Purpose |
| --- | --- |
| `@microsoft/applicationinsights-web` | Core RUM SDK (page views, AJAX, exceptions). |
| `@microsoft/applicationinsights-clickanalytics-js` | Auto-collect click telemetry. |
| `@microsoft/applicationinsights-react-js` | React plugin (router instrumentation, hooks, HOC, ErrorBoundary). |
| `@microsoft/applicationinsights-react-native` | React Native plugin (native crashes, sessions). |
| `@microsoft/applicationinsights-angularplugin-js` | Angular plugin (router events, ErrorHandler). |
| `@microsoft/applicationinsights-debugplugin-js` | Dev-only telemetry inspector. |
| `@microsoft/applicationinsights-perfmarkmeasure-js` | User Timing (`performance.mark/measure`) integration. |
## Installation
```bash
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
```
Typings ship with the package — no separate `@types/...` install needed.
## Connection String
The browser SDK requires a connection string at init time. **It ships in plaintext to clients** — Microsoft Entra ID auth is not supported for browser telemetry. Use a separate App Insights resource with local auth enabled for browser RUM if you need to isolate it from backend telemetry.
```bash
# 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=..."
```
## Quick Start (npm)
```typescript
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();
```
Call `loadAppInsights()` exactly once, as early as possible (before user interactions you want tracked). Then `trackPageView()` for the initial load — when `enableAutoRouteTracking` is on, subsequent route changes are automatic.
## Quick Start (SDK Loader Script)
Recommended when you want auto-updating SDK and zero build pipeline. Paste this as the **first** `<script>` in `<head>`:
```html
<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>
```
Loader-only API (queued until SDK loads): `trackEvent`, `trackPageView`, `trackException`, `trackTrace`, `trackDependencyData`, `trackMetric`, `trackPageViewPerformance`, `startTrackPage`, `stopTrackPage`, `startTrackEvent`, `stopTrackEvent`, `addTelemetryInitializer`, `setAuthenticatedUserContext`, `clearAuthenticatedUserContext`, `flush`.
## Core Tracking APIs
```typescript
// 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();
```
## Telemetry Initializers (enrichment & filtering)
Run for every envelope before send. Return `false` to drop.
```typescript
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
```typescript
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();
```
Mark elements with `data-ai-*` attributes; clicks are emitted as Custom Events with parent-content metadata.
## SPA Route Tracking
- **Built-in:** set `enableAutoRouteTracking: true`. Hooks `history.pushState/replaceState` and `popstate`.
- **React Router:** use `@microsoft/applicationinsights-react-js` `withAITracking` HOC (see [references/framework-extensions.md](references/framework-extensions.md)).
- **Manual:** call `appInsights.trackPageView({ name, uri })` in your router's `useEffect` on route change. Disable `enableAutoRouteTracking` to avoid double counting.
## Distributed Tracing (correlate to backend)
Set `distributedTracingMode: 2` (`DistributedTracingModes.AI_AND_W3C`). The SDK adds `traceparent` (and legacy `Request-Id`) to outbound `fetch`/`XHR`. Backends instrumented with **OpenTelemetry** (e.g. `@azure/monitor-opentelemetry`) auto-link to the browser's operation_Id.
For cross-origin calls, also set `enableCorsCorrelation: true` and add the calling origin to the **CORS exposed headers** on the API.
## GenAI Agent Traces (OTel semantic conventions)
When the browser invokes an AI agent (function-calling, tool-use, model calls direct from the client), emit App Insights **Dependency** telemetry whose attributes follow the OpenTelemetry **GenAI semantic conventions** so they are queryable alongside backend agent spans in App Insights / Log Analytics.
**Set the opt-in env first** so backend instrumentations agree on the same schema version:
```bash
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
```
### Required attribute keys (use the OTel names verbatim)
| Span / op | Required attributes |
| --- | --- |
| `invoke_agent {agent.name}` | `gen_ai.operation.name=invoke_agent`, `gen_ai.provider.name`, `gen_ai.agent.name`, `gen_ai.agent.id` (when known) |
| `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` well-known values: `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`.
> **Sensitive content opt-in.** `gen_ai.system_instructions`, `gen_ai.input.messages`, `gen_ai.output.messages`, `gen_ai.tool.call.arguments`, `gen_ai.tool.call.result` are **Opt-In** by default. Gate them behind a runtime flag and avoid them in production unless you have approved data handling.
### Pattern: invoke_agent + nested tool/model spans
```typescript
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);
}
```
The browser's `traceparent` is automatically attached to outbound `fetch` (when `distributedTracingMode: 2`), so downstream Azure OpenAI / agent backend spans hang under the same operation_Id in App Insights.
For the full attribute reference, well-known values, and content-capture guidance, see [references/agent-traces.md](references/agent-traces.md).
### KQL: query GenAI traces in App Insights
```kusto
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)
See [references/framework-extensions.md](references/framework-extensions.md) for full React, React Native, Angular, Next.js, and Vite recipes.
```typescript
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
```typescript
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();
```
## Performance — Web Vitals
Auto-collected: page-load timings via `PerformanceTiming` / `PerformanceNavigationTiming`. To add Core Web Vitals:
```typescript
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);
```
## Cookies & Privacy
```typescript
new ApplicationInsights({ config: {
connectionString,
isCookieUseDisabled: true, // hard-disable all cookies
cookieCfg: { enabled: true, domain: ".example.com", path: "/", expiry: 365 }
}});
```
To honor consent dynamically:
```typescript
appInsights.getCookieMgr().setEnabled(userGaveConsent);
appInsights.config.disableTelemetry = !userGaveConsent;
```
## Sampling
Server-side ingestion sampling (recommended) is configured on the App Insights resource. SDK-side sampling reduces network use:
```typescript
new ApplicationInsights({ config: { connectionString, samplingPercentage: 50 } });
```
Per-type sampling via telemetry initializer: drop with `return false` based on `item.baseType`.
## Offline / Send-on-Unload
The SDK uses `sendBeacon` (default `onunloadDisableBeacon: false`) to flush on `pagehide` / `unload`. For SPAs, also call `appInsights.flush()` before destructive transitions (logout, hard reload).
## Common Pitfalls
1. **Do not initialize twice.** Re-importing the module under different bundles produces duplicate page views. Use a single shared module export.
2. **Initialize before first user input** to avoid losing early clicks/exceptions.
3. **Connection string is public** — never reuse the same App Insights resource for backend secrets.
4. **`enableAutoRouteTracking` + manual `trackPageView`** = duplicates. Pick one.
5. **CORS distributed tracing** requires the API to allow `Request-Id`, `Request-Context`, `traceparent`, `tracestate` request headers and expose `Request-Context` response header.
6. **GenAI sensitive content** (`gen_ai.input.messages` etc.) is Opt-In — never log without an explicit runtime flag and approved data handling.
7. **Agent token usage is on `chat` spans, not `invoke_agent`** — copy aggregated usage to the parent agent span only if you know it.
8. **React StrictMode** double-invokes effects in dev — guard `loadAppInsights()` with a module-level singleton.
## Bundle Size
The full web SDK is ~110 KB minified (~36 KB gzipped). For aggressive budgets, use the **Loader Script** path so the SDK loads asynchronously off the critical path, or tree-shake unused plugins.
## Key Types
```typescript
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";
```
## Best Practices
1. **One singleton instance** exported from a single module.
2. **Initialize early** in the app entrypoint, before router setup.
3. **Use telemetry initializers** to attach `app.version`, `tenantId`, and to scrub PII / query-string secrets.
4. **Set `distributedTracingMode: 2`** and ensure your APIs accept/expose W3C trace context headers.
5. **For GenAI**, follow OTel `gen_ai.*` attribute names verbatim — they are queryable across browser and backend telemetry uniformly.
6. **Gate sensitive content capture** (`gen_ai.input.messages` / `gen_ai.output.messages`) behind a build-time or runtime opt-in.
7. **Flush on logout / sensitive navigation** so in-flight telemetry isn't dropped.
## References
- [references/agent-traces.md](references/agent-traces.md) — Full OTel GenAI semconv distilled (agent / model / tool spans, attributes, content capture).
- [references/framework-extensions.md](references/framework-extensions.md) — React, React Native, Angular, Next.js, Vite recipes.
- [references/configuration.md](references/configuration.md) — Full `IConfiguration` reference and tuning guide.
- Microsoft Learn: <https://learn.microsoft.com/azure/azure-monitor/app/javascript-sdk>
- ApplicationInsights-JS source: <https://github.com/microsoft/ApplicationInsights-JS>
- OTel GenAI semantic conventions: <https://opentelemetry.io/docs/specs/semconv/gen-ai/>
모든 파일
0개 파일applicationinsights-web-ts 설치
스킬 파일을 다운로드하여 .claude/skills/ 디렉터리에 압축을 풀어주세요.
ZIP 다운로드저장소를 클론하고 스킬 파일을 프로젝트에 복사하세요.
git clone https://github.com/microsoft/skills/tree/main/.github/skills/applicationinsights-web-ts # Copy SKILL.md to your .claude/skills/ directory
복사





집
