The Application Insights JavaScript SDK provides an OpenTelemetry (OTel) compatible tracing API, allowing you to instrument your applications using familiar OpenTelemetry-like APIs for distributed tracing while automatically sending telemetry to Azure Application Insights. This implementation focuses on tracing support only (not metrics or logs) and bridges the gap between OpenTelemetry’s vendor-neutral instrumentation patterns and Application Insights’ powerful monitoring capabilities.
Note: This is an OpenTelemetry-compatible tracing API implementation, not a full OpenTelemetry SDK. It provides a Tracing API interface following OpenTelemetry conventions but does not include all span operations, metrics or logging APIs.
OpenTelemetry is an open-source observability framework for cloud-native software. It provides a single set of APIs, libraries, and conventions for capturing distributed traces, metrics, and logs from your applications.
Application Insights Implementation: The Application Insights JavaScript SDK implements an OpenTelemetry like compatible tracing API. This means you can use familiar OpenTelemetry tracing patterns for distributed trace instrumentation. However, this is not a full OpenTelemetry SDK implementation - only the tracing API is supported (metrics and logs APIs are not included).
IOTelApi)The main entry point for OpenTelemetry functionality. Provides access to tracers and the trace API.
ITraceApi)Manages tracer instances and provides utilities for span context management.
IOTelTracer)Creates and manages spans. Each tracer typically represents a specific component or service.
IReadableSpan)Represents a unit of work in a distributed trace. Contains timing, attributes, and context information.
startActiveSpan: Creates a span, sets it as active, executes a callback, and automatically ends the span (recommended)startSpan: Creates a new span without setting it as active (manual lifecycle management)
setActiveSpan() if you want to change the active contextstartActiveSpan: Creates a span, sets it as active, executes a callback, and automatically ends the span (recommended)withSpan: Executes code with a span as the active contextuseSpan: Similar to withSpan but provides the span scope as a parameterwrapSpanContext: Creates a non-recording span from a span contextisSpanContextValid: Validates span context informationITraceHost)Direct access to OpenTelemetry trace operations available on appInsights or core instances:
startActiveSpan(name, options?, fn): Create a span with automatic lifecycle management (recommended)startSpan(name, options?, parent?): Create a new span with explicit parent control
getActiveSpan(createNew?): Get the currently active spansetActiveSpan(span): Set a span as the active span and manage contextThese methods provide direct control over span lifecycle and context management as the main appInsights manages an
internal Tracer (IOTelTracer).
The OpenTelemetry-compatible tracing APIs are built into the Application Insights packages:
npm install @microsoft/applicationinsights-web
# or for core only (by default does not initialize any trace provider
# which means core.startSpan() will return null)
npm install @microsoft/applicationinsights-core-js
No additional OpenTelemetry packages are required for tracing. The tracing API is included in the core SDK.
import { ApplicationInsights } from '@microsoft/applicationinsights-web';
// Initialize Application Insights
const appInsights = new ApplicationInsights({
config: {
connectionString: 'YOUR_CONNECTION_STRING'
}
});
appInsights.loadAppInsights();
// Get the OpenTelemetry API
const otelApi = appInsights.otelApi;
// Get a tracer for your service
const tracer = otelApi.trace.getTracer('my-service');
// Create a span
const span = tracer.startSpan('user-operation');
span.setAttribute('user.id', '12345');
span.setAttribute('operation.type', 'checkout');
try {
// Perform your operation
await processCheckout();
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
} finally {
span.end(); // Always end the span
}
startActiveSpan Helper (Recommended)The startActiveSpan standalone helper function provides automatic context management:
import { startActiveSpan } from '@microsoft/applicationinsights-core-js';
const result = await startActiveSpan(appInsights, 'process-payment', async (scope) => {
scope.span.setAttribute('payment.method', 'credit_card');
try {
const response = await processPayment();
scope.span.setAttribute('payment.status', 'success');
return response;
} catch (error) {
scope.span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
throw error;
}
// Span is automatically ended when function completes
});
The Application Insights SKU instance (appInsights) is itself a tracer, so you can call startSpan directly without obtaining a tracer first.
Important: startSpan() creates a span but does NOT set it as the active span. This means:
IDistributedTraceContext is NOT modifiedstartActiveSpan() helper or manually call setActiveSpan(span)// Direct usage - creates span but does NOT set it as active
const span = appInsights.startSpan('quick-operation', {
kind: OTelSpanKind.INTERNAL,
attributes: {
'user.id': '12345',
'operation.type': 'data-fetch'
}
});
if (span) {
try {
// Perform operation
const data = await fetchData();
span.setAttribute('items.count', data.length);
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
} finally {
span.end();
}
}
When to use direct startSpan vs obtaining a tracer:
appInsights.startSpan() directly (Recommended) - For most scenarios, provides simple and direct span creationappInsights.trace.getTracer('service-name') - Only when you need to organize spans by different services or components with specific names for better categorizationBoth approaches create identical telemetry, but using the direct startSpan method is simpler and recommended for most applications.
This folder contains comprehensive documentation on all OpenTelemetry features:
When you end a span, Application Insights automatically:
Create hierarchical traces with parent-child relationships:
tracer.startActiveSpan('parent-operation', (parentSpan) => {
parentSpan.setAttribute('step', 'starting');
// Child spans automatically inherit parent context
tracer.startActiveSpan('child-operation', (childSpan) => {
childSpan.setAttribute('detail', 'processing');
// Work here
});
parentSpan.setAttribute('step', 'completed');
});
Propagate trace context across service boundaries:
// Service A: Create a span and extract context
const span = tracer.startSpan('api-call');
const traceContext = span.spanContext();
// Pass traceContext to Service B (e.g., via HTTP headers)
const headers = {
'traceparent': `00-${traceContext.traceId}-${traceContext.spanId}-01`
};
// Service B: Create child span from propagated context
const childSpan = tracer.startSpan('process-request', {
parent: traceContext
});
Use different tracers for different parts of your application:
const userServiceTracer = otelApi.trace.getTracer('user-service');
const paymentTracer = otelApi.trace.getTracer('payment-service');
// Each tracer can be used independently
const userSpan = userServiceTracer.startSpan('authenticate');
const paymentSpan = paymentTracer.startSpan('process-payment');
The OpenTelemetry implementation in Application Insights JavaScript SDK supports:
The OpenTelemetry implementation is designed for minimal performance impact:
If you’re migrating from @opentelemetry/api:
@opentelemetry/api tracing imports with Application Insights importsappInsights.otelApi or appInsights.trace to access the tracing APIImportant Limitations:
Application Insights provides several methods to create spans:
Using Direct startSpan (Recommended):
const span = appInsights.startSpan('operation', options);
Using Tracer API (for organizing by service):
const tracer = appInsights.trace.getTracer('my-service');
const span = tracer.startSpan('operation', options);
Using startActiveSpan (for automatic context management):
appInsights.startActiveSpan('operation', (span) => {
// Work with automatic context and lifecycle management
});
The direct startSpan method is recommended for most scenarios. Use tracers when you need to organize spans by service name.
This implementation provides an OpenTelemetry-compatible tracing API based on OpenTelemetry API v1.9.0 specifications:
Scope: Only tracing APIs are implemented. This is not a complete OpenTelemetry SDK - metrics and logs APIs are not included.
startActiveSpan for most scenarios - Provides automatic lifecycle managementstartActiveSpanconst span = tracer.startSpan('risky-operation');
try {
await performOperation();
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
span.setAttribute('error', true);
span.setAttribute('error.message', error.message);
throw error;
} finally {
span.end();
}
tracer.startActiveSpan('async-work', async (span) => {
span.setAttribute('started', Date.now());
const result = await doAsyncWork();
span.setAttribute('completed', Date.now());
return result;
});
import { withSpan } from '@microsoft/applicationinsights-core-js';
const span = tracer.startSpan('background-task');
withSpan(appInsights.core, span, async () => {
// All nested operations inherit this span context
await processBackgroundWork();
});
span.end();
span.end()startActiveSpan or withSpan/useSpan helpersFor issues, questions, or feedback:
Learn about startActiveSpan for the recommended way to create spans