Configure Azure Monitor OpenTelemetry

This guide explains how to configure OpenTelemetry (OTel) in Azure Monitor Application Insights using the Azure Monitor OpenTelemetry distro. Proper configuration ensures consistent telemetry data collection across .NET, Java, Node.js, and Python applications, allowing for more reliable monitoring and diagnostics.

Connection string

A connection string in Application Insights defines the target location for sending telemetry data.

Use one of the following two ways to configure the connection string:

  • Set an environment variable.

    APPLICATIONINSIGHTS_CONNECTION_STRING=<Your Connection String>
    
  • Use a configuration object.

    // Import the useAzureMonitor function and the AzureMonitorOpenTelemetryOptions class from the @azure/monitor-opentelemetry package.
    const { useAzureMonitor, AzureMonitorOpenTelemetryOptions } = require("@azure/monitor-opentelemetry");
    
    // Create a new AzureMonitorOpenTelemetryOptions object.
    const options: AzureMonitorOpenTelemetryOptions = {
      azureMonitorExporterOptions: {
        connectionString: "<your connection string>"
      }
    };
    
    // Enable Azure Monitor integration using the useAzureMonitor function and the AzureMonitorOpenTelemetryOptions object.
    useAzureMonitor(options);
    

Set the Cloud Role Name and the Cloud Role Instance

For supported languages, the Azure Monitor OpenTelemetry Distro automatically detects the resource context and provides default values for the Cloud Role Name and the Cloud Role Instance properties of your component. However, you might want to override the default values to something that makes sense to your team. The cloud role name value appears on the Application Map as the name underneath a node.

Set the Cloud Role Name and the Cloud Role Instance via Resource attributes. Cloud Role Name uses service.namespace and service.name attributes, although it falls back to service.name if service.namespace isn't set. Cloud Role Instance uses the service.instance.id attribute value. For information on standard attributes for resources, see OpenTelemetry Semantic Conventions.

// Import the useAzureMonitor function, the AzureMonitorOpenTelemetryOptions class, the Resource class, and the SemanticResourceAttributes class from the @azure/monitor-opentelemetry, @opentelemetry/resources, and @opentelemetry/semantic-conventions packages, respectively.
const { useAzureMonitor, AzureMonitorOpenTelemetryOptions } = require("@azure/monitor-opentelemetry");
const { Resource } = require("@opentelemetry/resources");
const { SemanticResourceAttributes } = require("@opentelemetry/semantic-conventions");

// Create a new Resource object with the following custom resource attributes:
//
// * service_name: my-service
// * service_namespace: my-namespace
// * service_instance_id: my-instance
const customResource = new Resource({
  [SemanticResourceAttributes.SERVICE_NAME]: "my-service",
  [SemanticResourceAttributes.SERVICE_NAMESPACE]: "my-namespace",
  [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: "my-instance",
});

// Create a new AzureMonitorOpenTelemetryOptions object and set the resource property to the customResource object.
const options: AzureMonitorOpenTelemetryOptions = {
  resource: customResource
};

// Enable Azure Monitor integration using the useAzureMonitor function and the AzureMonitorOpenTelemetryOptions object.
useAzureMonitor(options);

Enable Sampling

You might want to enable sampling to reduce your data ingestion volume, which reduces your cost. Azure Monitor provides a custom fixed-rate sampler that populates events with a sampling ratio, which Application Insights converts to ItemCount. The fixed-rate sampler ensures accurate experiences and event counts. The sampler is designed to preserve your traces across services, and it's interoperable with older Application Insights Software Development Kits (SDKs). For more information, see Learn More about sampling.

Note

Metrics and Logs are unaffected by sampling.

The sampler expects a sample rate of between 0 and 1 inclusive. A rate of 0.1 means approximately 10% of your traces are sent.

// Import the useAzureMonitor function and the AzureMonitorOpenTelemetryOptions class from the @azure/monitor-opentelemetry package.
const { useAzureMonitor, AzureMonitorOpenTelemetryOptions } = require("@azure/monitor-opentelemetry");

// Create a new AzureMonitorOpenTelemetryOptions object and set the samplingRatio property to 0.1.
const options: AzureMonitorOpenTelemetryOptions = {
  samplingRatio: 0.1
};

// Enable Azure Monitor integration using the useAzureMonitor function and the AzureMonitorOpenTelemetryOptions object.
useAzureMonitor(options);

Tip

When using fixed-rate/percentage sampling and you aren't sure what to set the sampling rate as, start at 5%. (0.05 sampling ratio) Adjust the rate based on the accuracy of the operations shown in the failures and performance panes. A higher rate generally results in higher accuracy. However, ANY sampling affects accuracy so we recommend alerting on OpenTelemetry metrics, which are unaffected by sampling.

Live metrics

Live metrics provides a real-time analytics dashboard for insight into application activity and performance.

Important

See the Supplemental Terms of Use for Microsoft Azure Previews for legal terms that apply to Azure features that are in beta, preview, or otherwise not yet released into general availability.

Users can enable/disable Live Metrics when configuring the Distro using the enableLiveMetrics property.

const options: AzureMonitorOpenTelemetryOptions = {
    azureMonitorExporterOptions: {
        connectionString:
            process.env["APPLICATIONINSIGHTS_CONNECTION_STRING"] || "<your connection string>",
    },
    enableLiveMetrics: false
};

useAzureMonitor(options);

Offline Storage and Automatic Retries

Azure Monitor OpenTelemetry-based offerings cache telemetry when an application disconnects from Application Insights and retries sending for up to 48 hours. For data handling recommendations, see Export and delete private data. High-load applications occasionally drop telemetry for two reasons: exceeding the allowable time or exceeding the maximum file size. When necessary, the product prioritizes recent events over old ones.

By default, the AzureMonitorExporter uses one of the following locations for offline storage.

  • Windows
    • %TEMP%\Microsoft\AzureMonitor
  • Non-Windows
    • %TMPDIR%/Microsoft/AzureMonitor
    • /var/tmp/Microsoft/AzureMonitor

To override the default directory, you should set storageDirectory.

For example:

// Import the useAzureMonitor function and the AzureMonitorOpenTelemetryOptions class from the @azure/monitor-opentelemetry package.
const { useAzureMonitor, AzureMonitorOpenTelemetryOptions } = require("@azure/monitor-opentelemetry");

// Create a new AzureMonitorOpenTelemetryOptions object and set the azureMonitorExporterOptions property to an object with the following properties:
//
// * connectionString: The connection string for your Azure Monitor Application Insights resource.
// * storageDirectory: The directory where the Azure Monitor OpenTelemetry exporter will store telemetry data when it is offline.
// * disableOfflineStorage: A boolean value that specifies whether to disable offline storage.
const options: AzureMonitorOpenTelemetryOptions = {
  azureMonitorExporterOptions: {
    connectionString: "<Your Connection String>",
    storageDirectory: "C:\\SomeDirectory",
    disableOfflineStorage: false
  }
};

// Enable Azure Monitor integration using the useAzureMonitor function and the AzureMonitorOpenTelemetryOptions object.
useAzureMonitor(options);

To disable this feature, you should set disableOfflineStorage = true.

Enable the OTLP Exporter

You might want to enable the OpenTelemetry Protocol (OTLP) Exporter alongside the Azure Monitor Exporter to send your telemetry to two locations.

Note

The OTLP Exporter is shown for convenience only. We don't officially support the OTLP Exporter or any components or third-party experiences downstream of it.

  1. Install the OpenTelemetry Collector Trace Exporter and other OpenTelemetry packages in your project.

        npm install @opentelemetry/api
        npm install @opentelemetry/exporter-trace-otlp-http
        npm install @opentelemetry/sdk-trace-base
        npm install @opentelemetry/sdk-trace-node
    
  2. Add the following code snippet. This example assumes you have an OpenTelemetry Collector with an OTLP receiver running. For details, see the example on GitHub.

    // Import the useAzureMonitor function, the AzureMonitorOpenTelemetryOptions class, the trace module, the ProxyTracerProvider class, the BatchSpanProcessor class, the NodeTracerProvider class, and the OTLPTraceExporter class from the @azure/monitor-opentelemetry, @opentelemetry/api, @opentelemetry/sdk-trace-base, @opentelemetry/sdk-trace-node, and @opentelemetry/exporter-trace-otlp-http packages, respectively.
    const { useAzureMonitor, AzureMonitorOpenTelemetryOptions } = require("@azure/monitor-opentelemetry");
    const { BatchSpanProcessor } = require('@opentelemetry/sdk-trace-base');
    const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
    
    // Create a new OTLPTraceExporter object.
    const otlpExporter = new OTLPTraceExporter();
    
    // Enable Azure Monitor integration.
    const options: AzureMonitorOpenTelemetryOptions = {
        // Add the SpanEnrichingProcessor
        spanProcessors: [new BatchSpanProcessor(otlpExporter)] 
    }
    useAzureMonitor(options);
    

OpenTelemetry configurations

The following OpenTelemetry configurations can be accessed through environment variables while using the Azure Monitor OpenTelemetry Distros.

For more information about OpenTelemetry SDK configuration, see the OpenTelemetry documentation.

Redact URL Query Strings

To redact URL query strings, turn off query string collection. We recommend this setting if you call Azure storage using a SAS token.

When you're using the Azure Monitor OpenTelemetry distro package, query strings can be redacted via creating and applying a span processor to the distro configuration.

import { useAzureMonitor, AzureMonitorOpenTelemetryOptions } from "@azure/monitor-opentelemetry";
import { Context } from "@opentelemetry/api";
import { ReadableSpan, Span, SpanProcessor } from "@opentelemetry/sdk-trace-base";
import { SEMATTRS_HTTP_ROUTE, SEMATTRS_HTTP_TARGET, SEMATTRS_HTTP_URL } from "@opentelemetry/semantic-conventions";

class RedactQueryStringProcessor implements SpanProcessor {
  forceFlush(): Promise<void> {
	return Promise.resolve();
  }
  onStart(span: Span, parentContext: Context): void {
    return;
  }
  shutdown(): Promise<void> {
	return Promise.resolve();
  }
  onEnd(span: ReadableSpan) {
    const httpRouteIndex: number = String(span.attributes[SEMATTRS_HTTP_ROUTE]).indexOf('?');
    const httpUrlIndex: number = String(span.attributes[SEMATTRS_HTTP_URL]).indexOf('?');
    const httpTargetIndex: number = String(span.attributes[SEMATTRS_HTTP_TARGET]).indexOf('?');
    if (httpRouteIndex !== -1) {
      span.attributes[SEMATTRS_HTTP_ROUTE] = String(span.attributes[SEMATTRS_HTTP_ROUTE]).substring(0, httpRouteIndex);
    }
    if (httpUrlIndex !== -1) {
      span.attributes[SEMATTRS_HTTP_URL] = String(span.attributes[SEMATTRS_HTTP_URL]).substring(0, httpUrlIndex);
    }
    if (httpTargetIndex !== -1) {
      span.attributes[SEMATTRS_HTTP_TARGET] = String(span.attributes[SEMATTRS_HTTP_TARGET]).substring(0, httpTargetIndex);
    }
  }
}

const options: AzureMonitorOpenTelemetryOptions = {
  azureMonitorExporterOptions: {
      connectionString: <YOUR_CONNECTION_STRING>,
  },
  spanProcessors: [new RedactQueryStringProcessor()]
};

useAzureMonitor(options);