Azure Monitor OpenTelemetry Exporter for Java
⚠️ DEPRECATION NOTICE: This package is deprecated. Migrate to azure-monitor-opentelemetry-autoconfigure .
See Migration Guide for detailed instructions.
Export OpenTelemetry telemetry data to Azure Monitor / Application Insights.
Installation (Deprecated)
<dependency> <groupId>com.azure</groupId> <artifactId>azure-monitor-opentelemetry-exporter</artifactId> <version>1.0.0-beta.x</version> </dependency>
Recommended: Use Autoconfigure Instead
<dependency> <groupId>com.azure</groupId> <artifactId>azure-monitor-opentelemetry-autoconfigure</artifactId> <version>LATEST</version> </dependency>
Environment Variables
APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=xxx;IngestionEndpoint=https://xxx.in.applicationinsights.azure.com/
Basic Setup with Autoconfigure (Recommended)
Using Environment Variable
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder; import io.opentelemetry.api.OpenTelemetry; import com.azure.monitor.opentelemetry.exporter.AzureMonitorExporter;
// Connection string from APPLICATIONINSIGHTS_CONNECTION_STRING env var AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = AutoConfiguredOpenTelemetrySdk.builder(); AzureMonitorExporter.customize(sdkBuilder); OpenTelemetry openTelemetry = sdkBuilder.build().getOpenTelemetrySdk();
With Explicit Connection String
AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = AutoConfiguredOpenTelemetrySdk.builder(); AzureMonitorExporter.customize(sdkBuilder, "{connection-string}"); OpenTelemetry openTelemetry = sdkBuilder.build().getOpenTelemetrySdk();
Creating Spans
import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope;
// Get tracer Tracer tracer = openTelemetry.getTracer("com.example.myapp");
// Create span Span span = tracer.spanBuilder("myOperation").startSpan();
try (Scope scope = span.makeCurrent()) { // Your application logic doWork(); } catch (Throwable t) { span.recordException(t); throw t; } finally { span.end(); }
Adding Span Attributes
import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes;
Span span = tracer.spanBuilder("processOrder") .setAttribute("order.id", "12345") .setAttribute("customer.tier", "premium") .startSpan();
try (Scope scope = span.makeCurrent()) { // Add attributes during execution span.setAttribute("items.count", 3); span.setAttribute("total.amount", 99.99);
processOrder();
} finally { span.end(); }
Custom Span Processor
import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.ReadWriteSpan; import io.opentelemetry.sdk.trace.ReadableSpan; import io.opentelemetry.context.Context;
private static final AttributeKey<String> CUSTOM_ATTR = AttributeKey.stringKey("custom.attribute");
SpanProcessor customProcessor = new SpanProcessor() { @Override public void onStart(Context context, ReadWriteSpan span) { // Add custom attribute to every span span.setAttribute(CUSTOM_ATTR, "customValue"); }
@Override
public boolean isStartRequired() {
return true;
}
@Override
public void onEnd(ReadableSpan span) {
// Post-processing if needed
}
@Override
public boolean isEndRequired() {
return false;
}
};
// Register processor AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = AutoConfiguredOpenTelemetrySdk.builder(); AzureMonitorExporter.customize(sdkBuilder);
sdkBuilder.addTracerProviderCustomizer( (sdkTracerProviderBuilder, configProperties) -> sdkTracerProviderBuilder.addSpanProcessor(customProcessor) );
OpenTelemetry openTelemetry = sdkBuilder.build().getOpenTelemetrySdk();
Nested Spans
public void parentOperation() { Span parentSpan = tracer.spanBuilder("parentOperation").startSpan(); try (Scope scope = parentSpan.makeCurrent()) { childOperation(); } finally { parentSpan.end(); } }
public void childOperation() { // Automatically links to parent via Context Span childSpan = tracer.spanBuilder("childOperation").startSpan(); try (Scope scope = childSpan.makeCurrent()) { // Child work } finally { childSpan.end(); } }
Recording Exceptions
Span span = tracer.spanBuilder("riskyOperation").startSpan(); try (Scope scope = span.makeCurrent()) { performRiskyWork(); } catch (Exception e) { span.recordException(e); span.setStatus(StatusCode.ERROR, e.getMessage()); throw e; } finally { span.end(); }
Metrics (via OpenTelemetry)
import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.LongCounter; import io.opentelemetry.api.metrics.LongHistogram;
Meter meter = openTelemetry.getMeter("com.example.myapp");
// Counter LongCounter requestCounter = meter.counterBuilder("http.requests") .setDescription("Total HTTP requests") .setUnit("requests") .build();
requestCounter.add(1, Attributes.of( AttributeKey.stringKey("http.method"), "GET", AttributeKey.longKey("http.status_code"), 200L ));
// Histogram LongHistogram latencyHistogram = meter.histogramBuilder("http.latency") .setDescription("Request latency") .setUnit("ms") .ofLongs() .build();
latencyHistogram.record(150, Attributes.of( AttributeKey.stringKey("http.route"), "/api/users" ));
Key Concepts
Concept Description
Connection String Application Insights connection string with instrumentation key
Tracer Creates spans for distributed tracing
Span Represents a unit of work with timing and attributes
SpanProcessor Intercepts span lifecycle for customization
Exporter Sends telemetry to Azure Monitor
Migration to Autoconfigure
The azure-monitor-opentelemetry-autoconfigure package provides:
-
Automatic instrumentation of common libraries
-
Simplified configuration
-
Better integration with OpenTelemetry SDK
Migration Steps
Replace dependency:
<!-- Remove --> <dependency> <groupId>com.azure</groupId> <artifactId>azure-monitor-opentelemetry-exporter</artifactId> </dependency>
<!-- Add --> <dependency> <groupId>com.azure</groupId> <artifactId>azure-monitor-opentelemetry-autoconfigure</artifactId> </dependency>
Update initialization code per Migration Guide
Best Practices
-
Use autoconfigure — Migrate to azure-monitor-opentelemetry-autoconfigure
-
Set meaningful span names — Use descriptive operation names
-
Add relevant attributes — Include contextual data for debugging
-
Handle exceptions — Always record exceptions on spans
-
Use semantic conventions — Follow OpenTelemetry semantic conventions
-
End spans in finally — Ensure spans are always ended
-
Use try-with-resources — Scope management with try-with-resources pattern
Reference Links
Resource URL
Maven Package https://central.sonatype.com/artifact/com.azure/azure-monitor-opentelemetry-exporter
Migration Guide https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/monitor/azure-monitor-opentelemetry-exporter/MIGRATION.md
Autoconfigure Package https://central.sonatype.com/artifact/com.azure/azure-monitor-opentelemetry-autoconfigure
OpenTelemetry Java https://opentelemetry.io/docs/languages/java/
Application Insights https://learn.microsoft.com/azure/azure-monitor/app/app-insights-overview