Azure Monitor OpenTelemetry-based auto-instrumentation for Java applications

This article describes how to enable and configure the OpenTelemetry-based Azure Monitor Java offering. After you finish the instructions in this article, you'll be able to use Azure Monitor Application Insights to monitor your application.

Get started

Java auto-instrumentation can be enabled without any code changes.

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

Warning

If you're upgrading from 3.0 Preview:

  • Review all configuration options carefully. The JSON structure has completely changed. The file name is now all lowercase.

If you're upgrading from 3.0.x:

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

If you're upgrading from 3.1.x:

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

Point the JVM to the jar file

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

Tip

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

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=InstrumentationKey=...
      
    • Or you can create a configuration file named applicationinsights.json. Place it in the same directory as applicationinsights-agent-3.2.3.jar with the following content:

      {
        "connectionString": "InstrumentationKey=..."
      }
      
  2. Find the connection string on your Application Insights resource.

    Screenshot that shows the Application Insights 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 have the option to 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.

Instrumentation libraries

Java 3.x includes the following instrumentation libraries.

Autocollected requests

  • JMS consumers
  • Kafka consumers
  • Netty/WebFlux
  • 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

  • java.util.logging
  • Log4j, which includes MDC properties
  • SLF4J/Logback, which includes MDC properties

Autocollected metrics

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

Azure SDKs

Telemetry emitted by these Azure SDKs is autocollected by default:

Modify telemetry

This section explains how to modify telemetry.

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.

Add a custom dimension

Adding one or more custom dimensions populates the customDimensions field in the requests, dependencies, 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;
    
    Span.current().setAttribute("mycustomdimension", "myvalue1");
    

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;
    
    String traceId = Span.current().getSpanContext().getTraceId();
    String spanId = Span.current().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, and exceptions are supported through opentelemetry-api.
  • Any type 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
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 the OpenTelemetry API is generally available.

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();
    

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.3.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.3</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

For help with troubleshooting, see Troubleshooting.

Support

To get support:

OpenTelemetry feedback

To provide feedback:

Next steps