Skip to content

Azure mapping

The Azure Monitor exporter does not go through a collector: it turns each OpenTelemetry-shaped record into an Application Insights envelope and posts it to the ingestion endpoint itself. This page is the mapping, record by record - the same in the .NET encoder and in the browser script, so a page view from the browser and a request span from the server land in the tables and on the Application Map node you expect.

Endpoint

Envelopes are posted to {IngestionEndpoint}/v2.1/track, with the ingestion endpoint read from the connection string - https://dc.services.visualstudio.com when the connection string has none. The body is a JSON array of envelopes with Content-Type: application/json (gzip-compressed with Compression = BelemetryCompression.Gzip). With an AccessTokenProvider, every request also carries Authorization: Bearer - and such an exporter is never handed to the browser script.

Envelope

Every record becomes one envelope (a metric becomes one per point). name is Microsoft.ApplicationInsights.<Type>, baseType is <Type>Data, and the type-specific fields live in baseData.

{
  "ver": 1,
  "name": "Microsoft.ApplicationInsights.PageView",
  "time": "2026-10-15T09:30:12.3456789Z",
  "sampleRate": 100,
  "iKey": "00000000-0000-0000-0000-000000000000",
  "tags": {
    "ai.cloud.role": "[bitplatform]/belemetry-demo",
    "ai.cloud.roleInstance": "6f1c...",
    "ai.device.type": "Browser",
    "ai.internal.sdkVersion": "bitblmjs:10.6.2",
    "ai.location.ip": "0.0.0.0",
    "ai.operation.id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "ai.operation.name": "Checkout",
    "ai.session.id": "9c1e..."
  },
  "data": {
    "baseType": "PageViewData",
    "baseData": {
      "ver": 2,
      "id": "00f067aa0ba902b7",
      "name": "Checkout",
      "url": "https://myapp.example.com/checkout",
      "duration": "00:00:00",
      "properties": { "url.path": "/checkout", "browser.navigation.type": "push" }
    }
  }
}

Tags

TagValue
ai.cloud.role[service.namespace]/service.name, or service.name alone without a namespace - the same naming as the Azure Monitor OpenTelemetry exporter, so both land on one Application Map node
ai.cloud.roleInstanceservice.instance.id
ai.application.verservice.version
ai.operation.idThe trace id
ai.operation.parentIdThe parent span id (span) or the span id (log)
ai.operation.nameThe page name (page view) or the request name (server span: {method} {route} when both are known, else the span name); not set on other records
ai.session.idsession.id
ai.user.idenduser.pseudo.id
ai.user.authUserIduser.id
ai.user.agentuser_agent.original from the browser resource
ai.device.localebrowser.language from the browser resource
ai.device.type"Browser" (JS), "Phone" (Android and iOS), "PC" otherwise
ai.location.ip"0.0.0.0" when MaskIp (the default), so no IP-based geolocation
ai.internal.sdkVersion"bitblm:<version>" (.NET) or "bitblmjs:<version>" (JS)

session.id, enduser.pseudo.id and user.id are moved into the tags and not repeated as properties; without UserTracking consent the user tags are simply absent.

Record types

Source recordEnvelope typeTableFields
Span, kind SERVER or CONSUMER Request requests id, name ({method} {http.route} when the route is known), duration (d.hh:mm:ss.fffffff), responseCode, success (no error status and a status code below 500), url
Any other span RemoteDependency dependencies id, name, resultCode, data (the URL or the query text), duration, success (below 400), type (Ajax for browser HTTP, HTTP for .NET, the db.system.name for a database, InProc for internal spans), target
Log with exception.* Exception exceptions exceptions:[{id:1,outerId:0,typeName,message,hasFullStack,stack}], severityLevel
eventName == "browser.page_view" PageView pageViews name (page.title, else url.path), url, id
eventName == "browser.web_vital" Metric customMetrics metrics:[{name:"<web_vital.name>",kind:0,value,count:1}] - LCP, INP, CLS, FCP, TTFB
eventName == "browser.page_visit_time" Event customEvents name = PageVisitTime, measurements:{PageVisitTime:<ms>}, properties PageName and PageUrl - the Application Insights JS SDK's autoTrackPageVisitTime shape
Any other eventName Event customEvents name = the event name
Any other log Message traces message, severityLevel; the logger category as the CategoryName property
Metric point Metric customMetrics Gauge: the last value. Sum: the delta. Histogram: the delta sum, count, min and max. The meter name as ns; sums and histograms with nothing new since the last export are skipped

Application Insights takes deltas, so metrics go to Azure Monitor as deltas whatever Metrics.Temporality says - that setting applies to OTLP only.

Severity levels

OTLP severity numberseverityLevel
1-8 (TRACE, DEBUG)0 Verbose
9-12 (INFO)1 Information
13-16 (WARN)2 Warning
17-20 (ERROR)3 Error
21-24 (FATAL)4 Critical

Properties

Every attribute not consumed by a field becomes a custom property, stringified - so a structured log value, a TrackEvent attribute or a processor's enrichment is queryable as customDimensions["key"]. Keys are truncated to 150 characters and values to 8192, the limits the ingestion service enforces; messages and stack traces may be up to 32768.

Retries

Status codes 408, 429, 439 (daily quota), 500, 502, 503 and 504 are retried with backoff, honouring Retry-After, and kept for offline persistence when the retries run out. Anything else is a permanent answer and the batch is dropped.

A 206 is a partial success: the response lists, per item, the index in the array and its status code. Only the items whose code is one of the retryable ones above are sent again - rebuilt into a new array - and the rest, accepted or permanently rejected, are not.

API

BelemetryAzureMonitorExporterOptions Class

Settings of the Azure Monitor (Application Insights) exporter, which posts to the ingestion endpoint (/v2.1/track) directly, so page views, requests, dependencies, exceptions and custom events land in their usual Application Insights tables without a collector in between.

Name Type and default Description
ConnectionString string The Application Insights connection string (InstrumentationKey=...;IngestionEndpoint=https://...;LiveEndpoint=https://...). Defaults to APPLICATIONINSIGHTS_CONNECTION_STRING when set (outside the browser).
AccessTokenProvider Func<CancellationToken, ValueTask<string>> Supplies a Microsoft Entra ID access token (scope https://monitor.azure.com//.default) sent as Authorization: Bearer, for resources with local authentication disabled. Belemetry takes no dependency on Azure.Identity: pass e.g. ct => credential.GetTokenAsync(...).
MaskIp bool= true Whether to send ai.location.ip = 0.0.0.0 so the ingestion service does not derive the user's location from the client IP address. Defaults to true.
Compression BelemetryCompression= BelemetryCompression.None The request-body compression. Defaults to none.
Timeout TimeSpan= 00:00:30 The maximum time one export request may take. Defaults to 30 seconds.
EnableLiveMetrics bool= false Whether to stream Live Metrics (requests, dependencies, exceptions, CPU and memory, once per second while someone watches the Live Metrics blade). Not available in the browser. Defaults to false.
IncludeInBrowser bool= true Whether the browser script exports to Application Insights too (with BelemetryBrowserTransport.Direct). Defaults to true.
Signals BelemetrySignals= BelemetrySignals.All The signals sent to Application Insights. Defaults to all three.
MinimumLogLevel LogLevel? The least severe log level this exporter receives from the .NET pipeline (its own logs and the records the browser relays); plain log records below it are left out of this exporter's batches only. Events - page views, interactions, web vitals, custom events, exceptions - are not logs to a log level and always pass, as do spans and metrics. null (the default) sends every collected record. Use it when Application Insights should get warnings and errors only while an OTLP backend gets everything, as a per-provider logging level would with two logging providers.
An unhandled error has occurred. Reload 🗙