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).
- Familiar API: Use OpenTelemetry-like tracing APIs following industry-standard patterns
- Tracing Standards: Implement distributed tracing using OpenTelemetry conventions
- Automatic Telemetry: Spans automatically create Application Insights trace telemetry
- Rich Context: Full distributed tracing with parent-child span relationships
- Service Identification: Organize traces by service name and version
- Type Safety: Full TypeScript support with proper interfaces
- Backward Compatibility: Works alongside existing Application Insights code
- Single SDK: No need for separate OpenTelemetry packages for tracing
1. OTel API (IOTelApi)
The main entry point for OpenTelemetry functionality. Provides access to tracers and the trace API.
2. Trace API (ITraceApi)
Manages tracer instances and provides utilities for span context management.
3. Tracer (IOTelTracer)
Creates and manages spans. Each tracer typically represents a specific component or service.
4. Span (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)- Note: Does NOT change the active span or modify the current traceId/spanId on IDistributedTraceContext
- You must manually call
setActiveSpan()if you want to change the active context
startActiveSpan: 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 towithSpanbut provides the span scope as a parameterwrapSpanContext: Creates a non-recording span from a span contextisSpanContextValid: Validates span context information
7. Application Insights Functions (ITraceHost)
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- Note: Does NOT change the active span or modify the current traceId/spanId on IDistributedTraceContext
getActiveSpan(createNew?): Get the currently active spansetActiveSpan(span): Set a span as the active span and manage context
These 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-jsNo 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
}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:
- The span will not automatically become the parent of subsequently created spans
- The current traceId/spanId on
IDistributedTraceContextis NOT modified - If you need the span to be active, use
startActiveSpan()helper or manually callsetActiveSpan(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:
- Use
appInsights.startSpan()directly (Recommended) - For most scenarios, provides simple and direct span creation - Use
appInsights.trace.getTracer('service-name')- Only when you need to organize spans by different services or components with specific names for better categorization
Both 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:
- OTel API - Main OpenTelemetry API interface and creation
- Trace API - Tracer management and span utilities
- startActiveSpan - Create spans with automatic lifecycle management (recommended)
- withSpan - Execute code with active span context
- useSpan - Execute code with span scope parameter
- Examples - Comprehensive usage examples and patterns
When you end a span, Application Insights automatically:
- Creates trace telemetry with full context
- Includes all span attributes as custom properties
- Preserves parent-child relationships via trace/span IDs
- Calculates accurate timing and duration
- Recognizes Azure SDK attributes (including both legacy and current OpenTelemetry semantic conventions)
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:
- Modern browsers (Chrome, Firefox, Safari, Edge) - ES5 target
- Internet Explorer 8+ (with ES5 polyfills)
- Mobile browsers (iOS Safari, Android Chrome)
- Non-browser runtimes (Node.js, Web Workers)
The OpenTelemetry implementation is designed for minimal performance impact:
- Lazy Initialization: APIs are created only when accessed
- Efficient Caching: Tracers are cached and reused
- Non-blocking: Span operations don't block the browser UI
- Minimal Allocations: Optimized to reduce memory pressure
- Tree-shakable: Unused code can be eliminated by bundlers
If you're migrating from @opentelemetry/api:
- Replace
@opentelemetry/apitracing imports with Application Insights imports - Use
appInsights.otelApiorappInsights.traceto access the tracing API - Most tracing API signatures are compatible
- Telemetry automatically flows to Application Insights
Important Limitations:
- Only tracing APIs are supported (no metrics or logs APIs)
- This is an OpenTelemetry-compatible implementation, not the official OpenTelemetry SDK
- Some advanced OpenTelemetry features may not be available
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:
- Trace API v1.x - Core tracing functionality (tracers, spans, context)
- Context API v1.x - Active span context management (via ITraceHost)
- Span interface specifications - Compatible span attributes, events, and status
Scope: Only tracing APIs are implemented. This is not a complete OpenTelemetry SDK - metrics and logs APIs are not included.
- Use
startActiveSpanfor most scenarios - Provides automatic lifecycle management - Always end spans - Either manually or via
startActiveSpan - Set span status - Indicate success/failure explicitly with status codes
- Use descriptive names - Span names should clearly identify operations
- Add relevant attributes - Enrich spans with contextual information
- Use service-specific tracers - Organize telemetry by service/component
const 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();- Ensure spans are ended with
span.end() - Check that Application Insights is initialized
- Verify instrumentation key is correct
- Use
startActiveSpanorwithSpan/useSpanhelpers - Ensure parent span is active when creating child spans
- Check that span contexts are properly propagated
- Don't create excessive spans in tight loops
- Use sampling if generating high volume of traces
- Consider span lifecycle and ensure spans are ended promptly
- Application Insights Documentation
- OpenTelemetry Specification
- Distributed Tracing Guide
- Performance Monitoring
For issues, questions, or feedback:
Learn about startActiveSpan for the recommended way to create spans
Next Steps:
- Read the OTel API documentation for detailed API reference
- Explore comprehensive examples for common scenarios
- Learn about withSpan and useSpan helpers