﻿---
title: Migrate to EDOT Java from the Elastic APM Java agent
description: Migrate from the Elastic APM Java agent to the Elastic Distribution of OpenTelemetry Java (EDOT Java).
url: https://www.elastic.co/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/migration
products:
  - APM Agent
  - Elastic Cloud Serverless
  - Elastic Distribution of OpenTelemetry SDK
  - Elastic Observability
---

# Migrate to EDOT Java from the Elastic APM Java agent
Compared to the Elastic APM Java agent, the Elastic Distribution of OpenTelemetry Java presents a number of advantages:
- Fully automatic instrumentation with zero code changes. No need to modify application code.
- Capture, send, transform, and store data in an OpenTelemetry native way. This includes for example the ability to use all features of the OpenTelemetry SDK for manual tracing, data following semantic conventions, or ability to use intermediate collectors and processors.
- OpenTelemetry Java Instrumentation provides a [broad coverage of libraries, frameworks, and applications](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md).
- EDOT Java is built on top of OpenTelemetry SDK and conventions, ensuring compatibility with community tools, vendor-neutral backends, and so on.


## Migration steps

Follow these steps to migrate from the legacy Elastic APM Java agent to the Elastic Distribution of OpenTelemetry Java.
<stepper>
  <step title="(Optional) Migrate manual instrumentation API">
    Migrate usages of the [Elastic APM Agent API](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/public-api) to OpenTelemetry API:
    - For [Annotation API](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/public-api#api-annotation), refer to [OpenTelemetry Annotations](https://opentelemetry.io/docs/zero-code/java/agent/annotations/).
    - For [Transaction API](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/public-api#api-transaction), refer to [OpenTelemetry API](https://opentelemetry.io/docs/zero-code/java/agent/api/).

    <note>
      Migration of application code using these APIs and annotations is not strictly required when deploying the EDOT agent. If not migrated, spans, transactions, and metrics that were previously created with those custom API calls and annotations will no longer be generated. OpenTelemetry instrumentation coverage might replace the need for some or all of these custom code changes.
    </note>
  </step>

  <step title="Replace configuration options">
    Refer to the [Configuration mapping](#configuration-mapping). Refer to [Configuration](https://www.elastic.co/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/configuration) for ways to provide configuration settings.
  </step>

  <step title="Replace the agent binary">
    Remove the `-javaagent:` argument that contains the Elastic APM Java agent from the JVM arguments. Then add the `-javaagent:` argument to the JVM arguments to use EDOT Java, and restart the application or follow [Kubernetes instructions](https://www.elastic.co/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/setup/k8s) or [Runtime attach instructions](https://www.elastic.co/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/setup/runtime-attach) if applicable. Refer to [Setup](https://www.elastic.co/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/setup).
  </step>
</stepper>


## Configuration mapping

The following are Elastic APM Java agent settings that you can migrate to EDOT Java.

### `server_url`

The Elastic [`server_url`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-reporter#config-server-url) option corresponds to the OpenTelemetry [`OTEL_EXPORTER_OTLP_ENDPOINT`](https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_endpoint) option.

### `server_urls`

The Elastic [`server_urls`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-reporter#config-server-urls) option has no equivalent OpenTelemetry option. You can only specify one endpoint.
Use [OTEL_EXPORTER_OTLP_ENDPOINT](https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_endpoint) instead.

### `secret_token`

The Elastic [`secret_token`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-reporter#config-secret-token) option corresponds to the OpenTelemetry [OTEL_EXPORTER_OTLP_HEADERS](https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_headers) option.
For example: `OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer an_apm_secret_token"`.

### `api_key`

The Elastic [`api_key`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-reporter#config-api-key) option corresponds to the OpenTelemetry [OTEL_EXPORTER_OTLP_HEADERS](https://opentelemetry.io/docs/concepts/sdk-configuration/otlp-exporter-configuration/#otel_exporter_otlp_headers) option.
For example:`OTEL_EXPORTER_OTLP_HEADERS="Authorization=ApiKey an_api_key"`.

### `service_name`

The Elastic [`service_name`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-service-name) option corresponds to the OpenTelemetry [OTEL_SERVICE_NAME](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_service_name) option.
The service name value can also be set using [OTEL_RESOURCE_ATTRIBUTES](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_resource_attributes).
For example: `OTEL_RESOURCE_ATTRIBUTES=service.name=myservice`. If `OTEL_SERVICE_NAME` is set, it takes precedence over the resource attribute.

### `enabled`

The Elastic [`enabled`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-enabled) option corresponds to the OpenTelemetry [OTEL_JAVAAGENT_ENABLED](https://opentelemetry.io/docs/zero-code/java/agent/disable/) option.

### `service_version`

The Elastic [`service_version`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-service-version) option corresponds to setting the `service.version` key in [OTEL_RESOURCE_ATTRIBUTES](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_resource_attributes).
For example: `OTEL_RESOURCE_ATTRIBUTES=service.version=1.2.3`.

### `environment`

The Elastic [`environment`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-environment) option corresponds to setting the `deployment.environment.name` key in [OTEL_RESOURCE_ATTRIBUTES](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_resource_attributes).
For example: `OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=testing`.

### `global_labels`

The Elastic [`global_labels`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-global-labels) option corresponds to adding `key=value` comma separated pairs in [OTEL_RESOURCE_ATTRIBUTES](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_resource_attributes).
For example: `OTEL_RESOURCE_ATTRIBUTES=alice=first,bob=second`. Such labels will result in labels.key=value attributes on the server, e.g. labels.alice=first

### `trace_methods`

The Elastic [`trace_methods`](https://www.elastic.co/docs/reference/apm/agents/java/config-core#config-trace-methods) option can be replaced by the [`OTEL_INSTRUMENTATION_METHODS_INCLUDE`](https://opentelemetry.io/docs/zero-code/java/agent/annotations/#creating-spans-around-methods-with-otelinstrumentationmethodsinclude) OpenTelemetry option, however the syntax is different and the ability to use wildcards is more limited.

### `capture_jmx_metrics`

The Elastic [`capture_jmx_metrics`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-jmx#config-capture-jmx-metrics) option can be replaced by
[OpenTelemetry JMX Insight](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/instrumentation/jmx-metrics/javaagent/) feature which is included in EDOT Java.
The JMX Insight feature provides the following benefits:
- Ability to define custom metrics using YAML.
- Capturing metrics with pre-defined metrics by using `OTEL_JMX_TARGET_SYSTEM` configuration option.


### `capture_headers`

Replace the Elastic `capture_headers` option with the following options:
- `otel.instrumentation.http.server.capture-request-headers` for HTTP server request
- `otel.instrumentation.http.server.capture-response-headers` for HTTP server response
- `otel.instrumentation.http.client.capture-request-headers` for HTTP client request
- `otel.instrumentation.http.client.capture-response-headers` for HTTP client response
- `otel.instrumentation.messaging.experimental.capture-headers` for messaging

The `capture_headers` option is dynamically adjustable, while the `otel.*` options are statically set by startup and cannot be subsequently adjusted.

### `span_stack_trace_min_duration`

Replace the Elastic `span_stack_trace_min_duration` option with [`OTEL_JAVA_EXPERIMENTAL_SPAN_STACKTRACE_MIN_DURATION`](/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/features#span-stacktrace).

### `disable_instrumentations`

Replace the `disable_instrumentations` option, which allows to selectively disable instrumentation (opt-out), with `OTEL_INSTRUMENTATION_<name>_ENABLED` where `<name>` is the instrumentation name.
See [OpenTelemetry documentation](https://opentelemetry.io/docs/zero-code/java/agent/disable/) for reference and values.

### `enable_instrumentations`

The `enable_instrumentations` option allows to disable all instrumentation enabled by default and selectively enable instrumentation (opt-in) can be replaced with:
- `OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED` = `false` to disable instrumentations enabled by default.
- `OTEL_INSTRUMENTATION_<name>_ENABLED` = `true` where `<name>` is the name of the instrumentation to enable. See [OpenTelemetry documentation](https://opentelemetry.io/docs/zero-code/java/agent/disable/) for reference and values.


### `hostname`

The Elastic [`hostname`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-hostname) option corresponds to setting the `host.name` key in [OTEL_RESOURCE_ATTRIBUTES](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_resource_attributes).
For example: `OTEL_RESOURCE_ATTRIBUTES=host.name=myhost`.

### `service_node_name`

The Elastic [`service_node_name`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-service-node-name) option corresponds to setting the `service.instance.id` key in [OTEL_RESOURCE_ATTRIBUTES](https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_resource_attributes). Warning: by default this is a generated unique ID; if you set this it must be a unique value for each JVM otherwise metric views cannot be correctly aggregated nor disambiguated
For example: `OTEL_RESOURCE_ATTRIBUTES=service.instance.id=myserviceinstance001`.

### `cloud_provider`

The Elastic [`cloud_provider`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-core#config-cloud-provider) option corresponds to the per-provider `otel.resource.providers.{provider}.enabled` configuration options.
By default, with EDOT `otel.resource.providers.{provider}.enabled` is set to `true`, this is equivalent to the `cloud_provider` default valuem which is `auto`, or automatically detect cloud providers. Notice that this behavior differs from the contrib OpenTelemetry distribution.
When the cloud provider is known, or there is none, turning off the non-relevant providers with `otel.resource.providers.{provider}.enabled = false` allows to [minimize the application startup overhead](/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/overhead#optimizing-application-startup).

### `log_sending`

The Elastic [`log_sending`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-logging#config-log-sending) option allows capturing and
sending application logs directly to APM Server without storing them on disk and ingesting them with a separate tool.
With EDOT, application logs are automatically captured and sent by default.
This feature is controlled by `otel.logs.exporter`, which is set to `otlp` by default. You can turn it off by setting `otel.logs.exporter` to `none`.

### `verify_server_cert`

The Elastic [`verify_server_cert`](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/config-reporter#config-verify-server-cert) option allows you to disable server certificate validation.
With EDOT, the equivalent configuration option is `ELASTIC_OTEL_VERIFY_SERVER_CERT` (default `true`), see [configuration](/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/configuration#exporter-certificate-verification) for details.

## Limitations

The following limitations apply to EDOT Java.

### Supported Java versions

EDOT Java agent and OpenTelemetry Java instrumentation are only compatible with Java 8 and later.

### Missing instrumentations

Support for LDAP client instrumentation is not currently available in EDOT Java.

### Central and dynamic configuration

You can manage EDOT Java configurations through the [central configuration feature](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/solutions/observability/apm/apm-agents/central-configuration) in the Applications UI.
Refer to [Central configuration](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/opentelemetry/central-configuration) for more information.

### Span compression

EDOT Java does not implement [span compression](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/solutions/observability/apm/spans#apm-spans-span-compression).

### Breakdown metrics

EDOT Java is not sending metrics that power the [Breakdown metrics](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/solutions/observability/apm/metrics#_breakdown_metrics).

### No remote attach

There is currently no EDOT Java equivalent for starting the agent with the [remote attach](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/setup-attach-cli) capability. The `-javaagent:` option is the preferred startup mechanism.
A migration path is available for starting the agent with [self attach](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/reference/apm/agents/java/setup-attach-api), which is to use [runtime attachment](https://www.elastic.co/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/setup/runtime-attach). Some [limitations](/elastic/docs-builder/docs/2437/reference/opentelemetry/edot-sdks/java/setup/runtime-attach#limitations)
apply, and the agent must be started early during application startup.

### Micrometer turned off by default

By default, Micrometer instrumentation is inactive and doesn't capture metrics. To turn it on, use the `otel.instrumentation.micrometer.enabled=true` setting.

## Troubleshooting

If you're encountering issues during migration, refer to the [EDOT Java troubleshooting guide](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/2437/troubleshoot/ingest/opentelemetry/edot-sdks/java).