Azure Monitor OpenTelemetry-based auto-instrumentation for Java applications
This article describes how to enable and configure the OpenTelemetry-based Azure Monitor Java offering. It can be used for any environment, including on-premises. After you finish the instructions in this article, you can use Azure Monitor Application Insights to monitor your application.
Note
On March 31, 2025, support for instrumentation key ingestion will end. Instrumentation key ingestion will continue to work, but we'll no longer provide updates or support for the feature. Transition to connection strings to take advantage of new capabilities.
Get started
Java auto-instrumentation is enabled through configuration changes. No code changes are required.
Prerequisites
You need:
- A Java application using Java 8+.
- An Azure subscription: Create an Azure subscription for free.
- An Application Insights resource: Create an Application Insights resource.
Enable Azure Monitor Application Insights
This section shows you how to download the auto-instrumentation jar file.
Download the jar file
Download the applicationinsights-agent-3.4.8.jar file.
Warning
If you are upgrading from an earlier 3.x version, you may be impacted by changing defaults or slight differences in the data we collect. See the migration notes at the top of the release notes for 3.4.0, 3.3.0, 3.2.0, and 3.1.0 for more details.
Point the JVM to the jar file
Add -javaagent:"path/to/applicationinsights-agent-3.4.8.jar"
to your application's JVM args.
Tip
For help with configuring your application's JVM args, see Tips for updating your JVM args.
If you develop a Spring Boot application, you can replace the JVM argument by a programmatic configuration. For more information, see Using Azure Monitor Application Insights with Spring Boot.
Set the Application Insights connection string
There are two ways you can point the jar file to your Application Insights resource:
Set an environment variable:
APPLICATIONINSIGHTS_CONNECTION_STRING=<Copy connection string from Application Insights Resource Overview>
Create a configuration file named
applicationinsights.json
. Place it in the same directory asapplicationinsights-agent-3.4.8.jar
with the following content:{ "connectionString": "Copy connection string from Application Insights Resource Overview" }
Find the connection string on your Application Insights resource.
Confirm data is flowing
Run your application and open your Application Insights Resource tab in the Azure portal. It can take a few minutes for data to show up in the portal.
Note
If you can't run the application or you aren't getting data as expected, see the Troubleshooting section.
Important
If you have two or more services that emit telemetry to the same Application Insights resource, you're required to set cloud role names to represent them properly on the application map.
As part of using Application Insights instrumentation, we collect and send diagnostic data to Microsoft. This data helps us run and improve Application Insights. You can disable nonessential data collection. To learn more, see Statsbeat in Azure Application Insights.
Configuration options
In the applicationinsights.json file, you can also configure these settings:
- Cloud role name
- Cloud role instance
- Sampling
- JMX metrics
- Custom dimensions
- Telemetry processors (preview)
- Autocollected logging
- Autocollected Micrometer metrics, including Spring Boot Actuator metrics
- Heartbeat
- HTTP proxy
- Self-diagnostics
For more information, see Configuration options.
Auto-instrumentation
Java 3.x includes the following auto-instrumentation.
Autocollected requests
- JMS consumers
- Kafka consumers
- Netty
- Quartz
- Servlets
- Spring scheduling
Note
Servlet and Netty auto-instrumentation covers the majority of Java HTTP services, including Java EE, Jakarta EE, Spring Boot, Quarkus, and Micronaut.
Autocollected dependencies
Autocollected dependencies plus downstream distributed trace propagation:
- Apache HttpClient
- Apache HttpAsyncClient
- AsyncHttpClient
- Google HttpClient
- gRPC
- java.net.HttpURLConnection
- Java 11 HttpClient
- JAX-RS client
- Jetty HttpClient
- JMS
- Kafka
- Netty client
- OkHttp
Autocollected dependencies without downstream distributed trace propagation:
- Cassandra
- JDBC
- MongoDB (async and sync)
- Redis (Lettuce and Jedis)
Autocollected logs
- Logback (including MDC properties)
- Log4j (including MDC/Thread Context properties)
- JBoss Logging (including MDC properties)
- java.util.logging
Autocollected metrics
- Micrometer, including Spring Boot Actuator metrics
- JMX Metrics
Azure SDKs
Telemetry emitted by these Azure SDKs is automatically collected by default:
- Azure App Configuration 1.1.10+
- Azure Cognitive Search 11.3.0+
- Azure Communication Chat 1.0.0+
- Azure Communication Common 1.0.0+
- Azure Communication Identity 1.0.0+
- Azure Communication Phone Numbers 1.0.0+
- Azure Communication SMS 1.0.0+
- Azure Cosmos DB 4.22.0+
- Azure Digital Twins - Core 1.1.0+
- Azure Event Grid 4.0.0+
- Azure Event Hubs 5.6.0+
- Azure Event Hubs - Azure Blob Storage Checkpoint Store 1.5.1+
- Azure Form Recognizer 3.0.6+
- Azure Identity 1.2.4+
- Azure Key Vault - Certificates 4.1.6+
- Azure Key Vault - Keys 4.2.6+
- Azure Key Vault - Secrets 4.2.6+
- Azure Service Bus 7.1.0+
- Azure Storage - Blobs 12.11.0+
- Azure Storage - Blobs Batch 12.9.0+
- Azure Storage - Blobs Cryptography 12.11.0+
- Azure Storage - Common 12.11.0+
- Azure Storage - Files Data Lake 12.5.0+
- Azure Storage - Files Shares 12.9.0+
- Azure Storage - Queues 12.9.0+
- Azure Text Analytics 5.0.4+
Modify telemetry
This section explains how to modify telemetry.
Add spans by using the OpenTelemetry annotation
The simplest way to add your own spans is by using OpenTelemetry's @WithSpan
annotation.
Spans populate the requests
and dependencies
tables in Application Insights.
Note
This feature is only in 3.2.0 and later.
Add
opentelemetry-instrumentation-annotations-1.21.0.jar
(or later) to your application:<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-instrumentation-annotations</artifactId> <version>1.21.0</version> </dependency>
Use the
@WithSpan
annotation to emit a span each time your method is executed:import io.opentelemetry.instrumentation.annotations.WithSpan; @WithSpan(value = "your span name") public void yourMethod() { }
By default, the span will end up in the dependencies
table with dependency type InProc
.
If your method represents a background job that isn't already captured by auto-instrumentation,
we recommend that you apply the attribute kind = SpanKind.SERVER
to the @WithSpan
annotation
so that it will end up in the Application Insights requests
table.
Add spans by using the OpenTelemetry API
If the preceding OpenTelemetry @WithSpan
annotation doesn't meet your needs, you can add your spans by using the OpenTelemetry API.
Note
This feature is only in 3.2.0 and later.
Add
opentelemetry-api-1.0.0.jar
(or later) to your application:<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> <version>1.0.0</version> </dependency>
Use the
GlobalOpenTelemetry
class to create aTracer
:import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.trace.Tracer; static final Tracer tracer = GlobalOpenTelemetry.getTracer("com.example");
Create a span, make it current, and then end it:
Span span = tracer.spanBuilder("my first span").startSpan(); try (Scope ignored = span.makeCurrent()) { // do stuff within the context of this } catch (Throwable t) { span.recordException(t); } finally { span.end(); }
Add span events
You can use opentelemetry-api
to create span events, which populate the traces
table in Application Insights. The string passed in to addEvent()
is saved to the message
field within the trace.
Note
This feature is only in 3.2.0 and later.
Add
opentelemetry-api-1.0.0.jar
(or later) to your application:<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> <version>1.0.0</version> </dependency>
Add span events in your code:
import io.opentelemetry.api.trace.Span; Span.current().addEvent("eventName");
Add span attributes
You can use opentelemetry-api
to add attributes to spans. These attributes can include adding a custom business dimension to your telemetry. You can also use attributes to set optional fields in the Application Insights schema, such as User ID or Client IP.
Adding one or more span attributes populates the customDimensions
field in the requests
, dependencies
, traces
, or exceptions
table.
Note
This feature is only in 3.2.0 and later.
Add
opentelemetry-api-1.0.0.jar
(or later) to your application:<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> <version>1.0.0</version> </dependency>
Add custom dimensions in your code:
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.common.AttributeKey; AttributeKey attributeKey = AttributeKey.stringKey("mycustomdimension"); Span.current().setAttribute(attributeKey, "myvalue1");
Update span status and record exceptions
You can use opentelemetry-api
to update the status of a span and record exceptions.
Note
This feature is only in 3.2.0 and later.
Add
opentelemetry-api-1.0.0.jar
(or later) to your application:<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> <version>1.0.0</version> </dependency>
Set status to
error
and record an exception in your code:import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.StatusCode; Span span = Span.current(); span.setStatus(StatusCode.ERROR, "errorMessage"); span.recordException(e);
Set the user ID
Populate the user ID
field in the requests
, dependencies
, or exceptions
table.
Consult applicable privacy laws before you set the Authenticated User ID.
Note
This feature is only in 3.2.0 and later.
Add
opentelemetry-api-1.0.0.jar
(or later) to your application:<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> <version>1.0.0</version> </dependency>
Set
user_Id
in your code:import io.opentelemetry.api.trace.Span; Span.current().setAttribute("enduser.id", "myuser");
Get the trace ID or span ID
You can use opentelemetry-api
to get the trace ID or span ID. This action can be done to add these identifiers to existing logging telemetry to improve correlation when you debug and diagnose issues.
Note
This feature is only in 3.2.0 and later.
Add
opentelemetry-api-1.0.0.jar
(or later) to your application:<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-api</artifactId> <version>1.0.0</version> </dependency>
Get the request trace ID and the span ID in your code:
import io.opentelemetry.api.trace.Span; Span span = Span.current(); String traceId = span.getSpanContext().getTraceId(); String spanId = span.getSpanContext().getSpanId();
Custom telemetry
Our goal in Application Insights Java 3.x is to allow you to send your custom telemetry by using standard APIs.
We currently support Micrometer, popular logging frameworks, and the Application Insights Java Classic SDK. Application Insights Java 3.x automatically captures the telemetry sent through these APIs and correlates it with autocollected telemetry.
Supported custom telemetry
The following table represents currently supported custom telemetry types that you can enable to supplement the Java 3.x agent. To summarize:
- Custom metrics are supported through Micrometer.
- Custom exceptions and traces are supported through logging frameworks.
- Custom requests, dependencies, metrics, and exceptions are supported through the OpenTelemetry API.
- The remaining telemetry types are supported through the Application Insights Classic SDK.
Custom telemetry type | Micrometer | Logback, Log4j, JUL | OpenTelemetry API | Classic SDK |
---|---|---|---|---|
Custom events | Yes | |||
Custom metrics | Yes | Yes | Yes | |
Dependencies | Yes | Yes | ||
Exceptions | Yes | Yes | Yes | |
Page views | Yes | |||
Requests | Yes | Yes | ||
Traces | Yes | Yes |
Send custom metrics by using Micrometer
Add Micrometer to your application:
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-core</artifactId> <version>1.6.1</version> </dependency>
Use the Micrometer global registry to create a meter:
static final Counter counter = Metrics.counter("test.counter");
Use the counter to record metrics:
counter.increment();
The metrics will be ingested into the customMetrics table, with tags captured in the
customDimensions
column. You can also view the metrics in the metrics explorer under theLog-based metrics
metric namespace.Note
Application Insights Java replaces all non-alphanumeric characters (except dashes) in the Micrometer metric name with underscores. As a result, the preceding
test.counter
metric will show up astest_counter
.
Send custom traces and exceptions by using your favorite logging framework
Logback, Log4j, and java.util.logging are auto-instrumented. Logging performed via these logging frameworks is autocollected as trace and exception telemetry.
By default, logging is only collected when that logging is performed at the INFO level or higher. To change this level, see the configuration options.
Structured logging (attaching custom dimensions to your logs) can be accomplished in these ways:
- Logback MDC
- Log4j 2 MapMessage (a
MapMessage
key of"message"
will be captured as the log message) - Log4j 2 Thread Context
- Log4j 1.2 MDC
Send custom telemetry by using the Application Insights Classic SDK
Add
applicationinsights-core
to your application:<dependency> <groupId>com.microsoft.azure</groupId> <artifactId>applicationinsights-core</artifactId> <version>3.4.8</version> </dependency>
Create a
TelemetryClient
instance:static final TelemetryClient telemetryClient = new TelemetryClient();
Use the client to send custom telemetry:
Events
telemetryClient.trackEvent("WinGame");
Metrics
telemetryClient.trackMetric("queueLength", 42.0);
Dependencies
boolean success = false; long startTime = System.currentTimeMillis(); try { success = dependency.call(); } finally { long endTime = System.currentTimeMillis(); RemoteDependencyTelemetry telemetry = new RemoteDependencyTelemetry(); telemetry.setSuccess(success); telemetry.setTimestamp(new Date(startTime)); telemetry.setDuration(new Duration(endTime - startTime)); telemetryClient.trackDependency(telemetry); }
Logs
telemetryClient.trackTrace(message, SeverityLevel.Warning, properties);
Exceptions
try { ... } catch (Exception e) { telemetryClient.trackException(e); }
Troubleshooting
See the dedicated troubleshooting article.
Test connectivity between your application host and the ingestion service
Application Insights SDKs and agents send telemetry to get ingested as REST calls to our ingestion endpoints. You can test connectivity from your web server or application host machine to the ingestion service endpoints by using raw REST clients from PowerShell or curl commands. See Troubleshoot missing application telemetry in Azure Monitor Application Insights.
Release notes
See the release notes on GitHub.
Support
To get support:
- For help with troubleshooting, review the troubleshooting steps.
- For Azure support issues, open an Azure support ticket.
- For OpenTelemetry issues, contact the OpenTelemetry community directly.
OpenTelemetry feedback
To provide feedback:
- Fill out the OpenTelemetry community's customer feedback survey.
- Tell Microsoft about yourself by joining our OpenTelemetry Early Adopter Community.
- Engage with other Azure Monitor users in the Microsoft Tech Community.
- Make a feature request at the Azure Feedback Forum.
Next steps
- Review Java auto-instrumentation configuration options.
- To review the source code, see the Azure Monitor Java auto-instrumentation GitHub repository.
- To learn more about OpenTelemetry and its community, see the OpenTelemetry Java GitHub repository.
- To enable usage experiences, see Enable web or browser user monitoring.
Feedback
Submit and view feedback for