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'll be able to 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

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.4.jar file.

Warning

If you are upgrading from an earlier 3.x version,

Starting from 3.4.0:

  • Rate-limited sampling is now the default (if you have not configured a fixed percentage previously). By default, it will capture at most around 5 requests per second (along with their dependencies, traces and custom events). See fixed-percentage sampling if you wish to revert to the previous behavior of capturing 100% of requests.

Starting from 3.3.0:

  • LoggingLevel is not captured by default as part of Traces' custom dimension since that data is already captured in the SeverityLevel field. For details on how to re-enable this if needed, please see the config options
  • Exception records are no longer recorded for failed dependencies, they are only recorded for failed requests.

Starting from 3.2.0:

  • Controller "InProc" dependencies are no longer captured by default. For details on how to re-enable these, please see the config options.
  • Database dependency names are now more concise with the full (sanitized) query still present in the data field. HTTP dependency names are now more descriptive. This change can affect custom dashboards or alerts if they relied on the previous values. For details, see the 3.2.0 release notes.

Starting from 3.1.0:

  • The operation names and request telemetry names are now prefixed by the HTTP method, such as GET and POST. This change can affect custom dashboards or alerts if they relied on the previous values. For details, see the 3.1.0 release notes.

Point the JVM to the jar file

Add -javaagent:"path/to/applicationinsights-agent-3.4.4.jar" to your application's JVM args.

Tip

For help with configuring your application's JVM args, see Tips for updating your JVM args.

Tip

If you develop a Spring Boot application, you can replace the JVM argument by a programmatic configuration. More here.

Set the Application Insights connection string

  1. There are two ways you can point the jar file to your Application Insights resource:

    • You can set an environment variable:

      APPLICATIONINSIGHTS_CONNECTION_STRING=<Copy connection string from Application Insights Resource Overview>
      
    • Or you can create a configuration file named applicationinsights.json. Place it in the same directory as applicationinsights-agent-3.4.4.jar with the following content:

      {
        "connectionString": "Copy connection string from Application Insights Resource Overview"
      }
      
  2. Find the connection string on your Application Insights resource.

    Screenshot displaying Application Insights overview and connection string.

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.

Screenshot that shows the Application Insights Overview tab with server requests and server response time highlighted.

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, which include 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/WebFlux
  • Quartz
  • Servlets
  • Spring scheduling

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

  • Log4j (including MDC/Thread Context properties)
  • Logback (including MDC properties)
  • JBoss Logging (including MDC properties)
  • java.util.logging

Autocollected metrics

  • Micrometer, which includes Spring Boot Actuator metrics
  • JMX Metrics

Azure SDKs

Telemetry emitted by these Azure SDKs is automatically collected by default:

Modify telemetry

This section explains how to modify telemetry.

Add spans

The easiest way to add your own spans is 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.

  1. Add opentelemetry-extension-annotations-1.16.0.jar to your application:

    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-extension-annotations</artifactId>
      <version>1.16.0</version>
    </dependency>
    
  2. Use the @WithSpan annotation to emit a span each time your method is executed:

     import io.opentelemetry.extension.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 is not already captured by auto-instrumentation, it is recommended to apply the attribute kind = SpanKind.SERVER to the @WithSpan annotation so that it will end up in the Application Insights requests table.

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.

  1. Add opentelemetry-api-1.6.0.jar to your application:

    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-api</artifactId>
      <version>1.6.0</version>
    </dependency>
    
  2. 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.

  1. Add opentelemetry-api-1.6.0.jar to your application:

    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-api</artifactId>
      <version>1.6.0</version>
    </dependency>
    
  2. 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.

  1. Add opentelemetry-api-1.6.0.jar to your application:

    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-api</artifactId>
      <version>1.6.0</version>
    </dependency>
    
  2. 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.

Important

Consult applicable privacy laws before you set Authenticated User ID.

Note

This feature is only in 3.2.0 and later.

  1. Add opentelemetry-api-1.6.0.jar to your application:

    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-api</artifactId>
      <version>1.6.0</version>
    </dependency>
    
  2. 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.

  1. Add opentelemetry-api-1.6.0.jar to your application:

    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-api</artifactId>
      <version>1.6.0</version>
    </dependency>
    
  2. 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 2.x 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 opentelemetry-api.
  • All types of the custom telemetry is supported through the Application Insights Java 2.x SDK.
Custom telemetry type Micrometer Log4j, logback, JUL 2.x SDK opentelemetry-api
Custom events Yes
Custom metrics Yes Yes Yes
Dependencies Yes Yes
Exceptions Yes Yes Yes
Page views Yes
Requests Yes Yes
Traces Yes Yes

Currently, we're not planning to release an SDK with Application Insights 3.x.

Application Insights Java 3.x is already listening for telemetry that's sent to the Application Insights Java 2.x SDK. This functionality is an important part of the upgrade story for existing 2.x users. And it fills an important gap in our custom telemetry support until all custom telemetry types are supported via the OpenTelemetry API.

Send custom metrics by using Micrometer

  1. Add Micrometer to your application:

    <dependency>
      <groupId>io.micrometer</groupId>
      <artifactId>micrometer-core</artifactId>
      <version>1.6.1</version>
    </dependency>
    
  2. Use the Micrometer global registry to create a meter:

    static final Counter counter = Metrics.counter("test.counter");
    
  3. Use the counter to record metrics:

    counter.increment();
    
  4. 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 the "Log-based metrics" metric namespace.

    Note

    Application Insights Java replaces all non-alphanumeric characters (except dashes) in the Micrometer metric name with underscores, so the test.counter metric above will show up as test_counter.

Send custom traces and exceptions by using your favorite logging framework

Log4j, Logback, 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 above. To change this level, see the configuration options.

If you want to attach custom dimensions to your logs, use Log4j 1.2 MDC, Log4j 2 MDC, or Logback MDC. Application Insights Java 3.x automatically captures those MDC properties as custom dimensions on your trace and exception telemetry.

Send custom telemetry by using the 2.x SDK

  1. Add applicationinsights-core-2.6.4.jar to your application. All 2.x versions are supported by Application Insights Java 3.x. If you have a choice, it's worth using the latest version:

    <dependency>
      <groupId>com.microsoft.azure</groupId>
      <artifactId>applicationinsights-core</artifactId>
      <version>2.6.4</version>
    </dependency>
    
  2. Create a TelemetryClient:

    static final TelemetryClient telemetryClient = new TelemetryClient();
    
  3. 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:

OpenTelemetry feedback

To provide feedback:

Next steps