applicationinsights-web-ts

Instrumentez les applications browser/web avec le SDK JavaScript Application Insights (@microsoft/applicationinsights-web). Utilisé pour le Real User Monitoring (RUM) — pages vues, clics, dépendances AJAX/fetch, exceptions, événements personnalisés et traces d'agents GenAI côté navigateur corrélées aux traces OpenTelemetry backend. Couvre le SDK Loader Script et la configuration npm, les extensions de framework (React, React Native, Angular), le Click Analytics, les initialiseurs de télémétrie, et les conventions sémantiques OTel GenAI pour les spans agent/tool/model émis depuis le navigateur.

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

SDK JavaScript Application Insights (Web) pour TypeScript

Surveillance utilisateur réel (RUM) pour les apps navigateur avec @microsoft/applicationinsights-web. Collecte automatiquement les pages visitées, les dépendances AJAX/fetch, les exceptions non gérées et (avec le plugin Click Analytics) les clics. Supporte les événements personnalisés, les métriques et les traces d'agent GenAI qui suivent les conventions sémantiques GenAI d'OpenTelemetry et se corrèlent aux spans backend via W3C Trace Context.

Distinct de azure-monitor-opentelemetry-ts, qui est pour les apps serveur Node.js. Cette skill concerne le code navigateur/web (et React Native).

Avant l'implémentation

Cherchez microsoft-docs MCP pour les patterns API actuels :

  • Requête : "Application Insights JavaScript SDK setup"
  • Requête : "Application Insights JavaScript SDK configuration"
  • Requête : "Application Insights JavaScript framework extensions React Angular"
  • Vérifiez la version du package : npm view @microsoft/applicationinsights-web version

Packages

Package Finalité
@microsoft/applicationinsights-web SDK RUM principal (pages, AJAX, exceptions).
@microsoft/applicationinsights-clickanalytics-js Collecte auto de la télémétrie des clics.
@microsoft/applicationinsights-react-js Plugin React (instrumentation du routeur, hooks, HOC, ErrorBoundary).
@microsoft/applicationinsights-react-native Plugin React Native (crashs natifs, sessions).
@microsoft/applicationinsights-angularplugin-js Plugin Angular (événements du routeur, ErrorHandler).
@microsoft/applicationinsights-debugplugin-js Inspecteur de télémétrie dev-only.
@microsoft/applicationinsights-perfmarkmeasure-js Intégration User Timing (performance.mark/measure).

Installation

npm i --save @microsoft/applicationinsights-web
# Plugins optionnels (installez uniquement ceux que vous utilisez) :
npm i --save @microsoft/applicationinsights-clickanalytics-js
npm i --save @microsoft/applicationinsights-react-js @microsoft/applicationinsights-react-native @microsoft/applicationinsights-angularplugin-js

Les typages sont inclus avec le package — aucune installation séparée @types/... n'est nécessaire.

Chaîne de connexion

Le SDK navigateur nécessite une chaîne de connexion au moment de l'init. Elle est expédiée en texte brut aux clients — l'authentification Microsoft Entra ID n'est pas supportée pour la télémétrie navigateur. Utilisez une ressource App Insights séparée avec authentification locale activée pour le RUM navigateur si vous devez l'isoler de la télémétrie backend.

# Vite / CRA / Next.js — exposez aux clients via le préfixe env public
VITE_APPINSIGHTS_CONNECTION_STRING="InstrumentationKey=...;IngestionEndpoint=https://...;LiveEndpoint=https://..."
NEXT_PUBLIC_APPINSIGHTS_CONNECTION_STRING="InstrumentationKey=..."

Démarrage rapide (npm)

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

export const appInsights = new ApplicationInsights({
  config: {
    connectionString: import.meta.env.VITE_APPINSIGHTS_CONNECTION_STRING,
    enableAutoRouteTracking: true,        // Changements de route SPA -> pages visitées
    enableCorsCorrelation: true,          // Propagez Request-Id / traceparent à AJAX cross-origin
    enableRequestHeaderTracking: true,
    enableResponseHeaderTracking: true,
    distributedTracingMode: 2,            // DistributedTracingModes.AI_AND_W3C — émettez traceparent pour corrélation backend
    autoTrackPageVisitTime: true,
    disableFetchTracking: false,          // fetch() est auto-instrumenté par défaut
    excludeRequestFromAutoTrackingPatterns: [/livemetrics\.azure\.com/i]
  }
});

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

Appelez loadAppInsights() exactement une fois, aussi tôt que possible (avant les interactions utilisateur que vous voulez tracker). Puis trackPageView() pour le chargement initial — quand enableAutoRouteTracking est activé, les changements de route suivants sont automatiques.

Démarrage rapide (script du chargeur SDK)

Recommandé quand vous voulez un SDK auto-mis à jour et zéro pipeline de build. Collez ceci comme le premier <script> dans <head> :

<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) {
    /* Voir : https://learn.microsoft.com/azure/azure-monitor/app/javascript-sdk
       Utilisez le dernier snippet de la page Microsoft Learn ci-dessus — il inclut
       le basculement CDN de secours (cr), le rapport de non-chargement SDK et le shim queue
       donc les appels avant que le SDK soit prêt ne sont pas perdus. */
  }({ src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
      crossOrigin: "anonymous",
      cfg: { connectionString: "YOUR_CONNECTION_STRING" } });
</script>

API chargeur-only (mise en queue jusqu'au chargement du SDK) : trackEvent, trackPageView, trackException, trackTrace, trackDependencyData, trackMetric, trackPageViewPerformance, startTrackPage, stopTrackPage, startTrackEvent, stopTrackEvent, addTelemetryInitializer, setAuthenticatedUserContext, clearAuthenticatedUserContext, flush.

APIs de tracking principal

// Pages visitées (SPAs qui désactivent enableAutoRouteTracking)
appInsights.trackPageView({ name: "Checkout", uri: "/checkout", properties: { cartSize: 3 } });

// Événements personnalisés (actions utilisateur, événements métier)
appInsights.trackEvent({ name: "PurchaseCompleted" }, { orderId: "ord_123", amountUsd: 49.95 });

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

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

// Métriques personnalisées (numériques)
appInsights.trackMetric({ name: "checkout.duration_ms", average: 1234 });

// Dépendances (appels sortants trackés manuellement — fetch/XHR sont auto-trackés)
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"
});

// Identité utilisateur (défini UNE FOIS par session authentifiée — les valeurs sont PII ; ne passez pas les emails)
appInsights.setAuthenticatedUserContext("user-id-123", "tenant-456", /*storeInCookie*/ true);
appInsights.clearAuthenticatedUserContext(); // à la déconnexion

// Force l'envoi avant déchargement
appInsights.flush();

Initialiseurs de télémétrie (enrichissement & filtrage)

S'exécutent pour chaque enveloppe avant envoi. Retournez false pour rejeter.

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;

  // Rejetez les pages visitées de santé bruyantes
  if (item.baseType === "PageviewData" && item.baseData?.uri?.endsWith("/healthz")) return false;

  // Nettoyez les secrets de chaîne de requête
  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();

Marquez les éléments avec des attributs data-ai-* ; les clics sont émis en tant qu'événements personnalisés avec métadonnées du contenu parent.

Tracking de route SPA

  • Intégré : mettez enableAutoRouteTracking: true. Hooks history.pushState/replaceState et popstate.
  • React Router : utilisez le HOC withAITracking de @microsoft/applicationinsights-react-js (voir references/framework-extensions.md).
  • Manuel : appelez appInsights.trackPageView({ name, uri }) dans le useEffect du routeur au changement de route. Désactivez enableAutoRouteTracking pour éviter le double comptage.

Distributed Tracing (corrélation au backend)

Mettez distributedTracingMode: 2 (DistributedTracingModes.AI_AND_W3C). Le SDK ajoute traceparent (et l'ancien Request-Id) à fetch/XHR sortant. Les backends instrumentés avec OpenTelemetry (par exemple @azure/monitor-opentelemetry) se lient auto aux operation_Id du navigateur.

Pour les appels cross-origin, mettez aussi enableCorsCorrelation: true et ajoutez l'origine appelante aux en-têtes exposés CORS sur l'API.

Traces d'agent GenAI (conventions sémantiques OTel)

Quand le navigateur invoque un agent IA (function-calling, tool-use, appels modèle direct du client), émettez une télémétrie Dependency d'App Insights dont les attributs suivent les conventions sémantiques GenAI d'OpenTelemetry pour qu'elles soient interrogeables aux côtés des spans d'agent backend dans App Insights / Log Analytics.

Définissez d'abord l'env opt-in pour que les instrumentations backend se mettent d'accord sur la même version de schéma :

OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental

Clés d'attribut requises (utilisez les noms OTel textuellement)

Span / op Attributs requis
invoke_agent {agent.name} gen_ai.operation.name=invoke_agent, gen_ai.provider.name, gen_ai.agent.name, gen_ai.agent.id (quand connu)
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

Valeurs bien connues de 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.

Opt-in contenu sensible. gen_ai.system_instructions, gen_ai.input.messages, gen_ai.output.messages, gen_ai.tool.call.arguments, gen_ai.tool.call.result sont Opt-In par défaut. Gardez-les derrière un flag runtime et évitez-les en prod sauf si vous avez approuvé le traitement des données.

Pattern : invoke_agent + spans imbriqués tool/model

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>
        });
      }
    }
  };
}

// Invocation d'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 chat completion imbriqué
  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"
  });

  // Span exécution d'outil imbriqué
  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);
}

Le traceparent du navigateur est automatiquement attaché à fetch sortant (quand distributedTracingMode: 2), donc les spans agent/Azure OpenAI en aval pendent sous le même operation_Id dans App Insights.

Pour la référence complète d'attributs, les valeurs bien connues et les conseils de capture de contenu, voir references/agent-traces.md.

KQL : interroger les traces GenAI dans App Insights

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)

Voir references/framework-extensions.md pour les recettes complètes React, React Native, Angular, Next.js et Vite.

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();

Performance — Web Vitals

Auto-collectés : timings de chargement de page via PerformanceTiming / PerformanceNavigationTiming. Pour ajouter 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);

Cookies & Privacy

new ApplicationInsights({ config: {
  connectionString,
  isCookieUseDisabled: true,         // Désactiver dur tous les cookies
  cookieCfg: { enabled: true, domain: ".example.com", path: "/", expiry: 365 }
}});

Pour honorer le consentement dynamiquement :

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

Sampling

Le sampling d'ingestion côté serveur (recommandé) est configuré sur la ressource App Insights. Le sampling côté SDK réduit l'utilisation réseau :

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

Sampling par type via initialiseur de télémétrie : rejetez avec return false basé sur item.baseType.

Offline / Send-on-Unload

Le SDK utilise sendBeacon (défaut onunloadDisableBeacon: false) pour vider sur pagehide / unload. Pour SPAs, appelez aussi appInsights.flush() avant les transitions destructives (déconnexion, rechargement dur).

Pièges courants

  1. N'initialisez pas deux fois. Ré-importer le module sous différents bundles produit des pages visitées en double. Utilisez une seule export de module partagé.
  2. Initialisez avant la première interaction utilisateur pour éviter de perdre les clics/exceptions précoces.
  3. La chaîne de connexion est publique — ne réutilisez jamais la même ressource App Insights pour les secrets backend.
  4. enableAutoRouteTracking + trackPageView manuel = doublons. Choisissez-en un.
  5. CORS distributed tracing nécessite que l'API autorise les en-têtes de requête Request-Id, Request-Context, traceparent, tracestate et expose l'en-tête de réponse Request-Context.
  6. Contenu sensible GenAI (gen_ai.input.messages etc.) est Opt-In — ne loggez jamais sans un flag runtime explicite et traitement des données approuvé.
  7. L'utilisation de tokens d'agent est sur les spans chat, pas invoke_agent — copiez l'utilisation agrégée au span d'agent parent uniquement si vous la connaissez.
  8. React StrictMode double-invoque les effects en dev — gardez loadAppInsights() avec un singleton au niveau du module.

Taille du bundle

Le SDK web complet fait ~110 KB minifié (~36 KB gzippé). Pour budgets agressifs, utilisez le chemin Loader Script pour que le SDK se charge asynchronement hors du chemin critique, ou tree-shake les plugins inutilisés.

Types clés

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";

Bonnes pratiques

  1. Une seule instance singleton exportée depuis un seul module.
  2. Initialisez tôt dans le point d'entrée de l'app, avant la configuration du routeur.
  3. Utilisez les initialiseurs de télémétrie pour attacher app.version, tenantId et pour nettoyer les PII / secrets de chaîne de requête.
  4. Mettez distributedTracingMode: 2 et assurez-vous que vos APIs acceptent/exposent les en-têtes de contexte de trace W3C.
  5. Pour GenAI, suivez les noms d'attribut OTel gen_ai.* textuellement — ils sont interrogeables unifié sur la télémétrie navigateur et backend.
  6. Gardez la capture de contenu sensible (gen_ai.input.messages / gen_ai.output.messages) derrière un opt-in au moment du build ou runtime.
  7. Videz à la déconnexion / navigation sensible pour que la télémétrie en vol ne soit pas perdue.

Références

Skills similaires