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:

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.9.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.9.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

  1. 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 as applicationinsights-agent-3.4.9.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 that shows 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, 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:

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.

  1. 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>
    
  2. 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.

  1. 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>
    
  2. Use the GlobalOpenTelemetry class to create a Tracer:

     import io.opentelemetry.api.GlobalOpenTelemetry;
     import io.opentelemetry.api.trace.Tracer;
    
     static final Tracer tracer = GlobalOpenTelemetry.getTracer("com.example");
    
  3. 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.

  1. 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>
    
  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.0.0.jar (or later) to your application:

    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-api</artifactId>
      <version>1.0.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.0.0.jar (or later) to your application:

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

Consult applicable privacy laws before you set the Authenticated User ID.

Note

This feature is only in 3.2.0 and later.

  1. 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>
    
  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.0.0.jar (or later) to your application:

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

  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. As a result, the preceding test.counter metric will show up as test_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:

Send custom telemetry by using the Application Insights Classic SDK

  1. Add applicationinsights-core to your application:

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

    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