Zero-Code Instrumentation of Java using OpenTelemetry
6 minute read
Overview
Zero-code instrumentation in Java with OpenTelemetry uses a Java agent that attaches to any Java 8+ application (but certain instrumentations require Java 11+). This approach requires no changes to the application code itself, as the agent dynamically injects bytecode to capture telemetry from popular libraries and frameworks. This is particularly useful for capturing telemetry at the boundaries of an application, such as incoming requests, database calls, and outbound HTTP requests.
Download the Java Agent
Visit the OpenTelemetry Java Instrumentation Releases page and download the latest version of opentelemetry-javaagent.jar from the list of assets. This JAR file contains the necessary bytecode instrumentation libraries which will automatically instrument your application at runtime. Place the opentelemetry-javaagent.jar file within your project directory or a designated folder where your Java applications reside. This will make it convenient to reference the agent in your application startup commands in the next step.
Define the Agent and Properties
To use the Java agent, you can either modify your application’s startup command or define the agent and properties using environment variables:
Direct Command-Line Configuration
Modify your Java application’s startup command by adding the -javaagent parameter followed by the path to the downloaded opentelemetry-javaagent.jar file. This will load the agent along with your application. You should also define a service name for your application to help identifying your service in telemetry data. Add the -Dotel.service.name system property to specify this.
java -javaagent:/path/to/opentelemetry-javaagent.jar -Dotel.service.name=my-service -jar yourapp.jar
Replace my-service with a meaningful name for your application, replace /path/to/ with the path to the opentelemetry-javaagent.jar file you downloaded, and replace yourapp with the name of your application jar.
Note: Don’t run this command yet - there is more configuration required in the following sections.
(Alternative) Use Environment Variables
Instead of modifying your Java application’s startup command, you can define the Java agent and other configuration properties using environment variables. This is especially useful in containerized environments.
export JAVA_TOOL_OPTIONS="-javaagent:/path/to/opentelemetry-javaagent.jar"
export OTEL_SERVICE_NAME="my-service"
Replace my-service with a meaningful name for your application, replace /path/to/ with the path to the opentelemetry-javaagent.jar file you downloaded.
Configure Exporters
You configure OTLP exporters in your Java application to send telemetry (logs, traces, and metrics) to Edge Delta. The configuration differs depending on whether you’re sending to an Edge Pipeline (local Edge Delta agent) or a Cloud Pipeline (Edge Delta hosted infrastructure).
Edge Pipeline Configuration
Use this configuration when sending telemetry to an Edge Delta agent running in your environment. This is the typical setup for Kubernetes deployments or when the Edge Delta agent runs on the same host or network as your application.
What you configure:
| Component | Configuration |
|---|---|
| Java application | OTLP exporter endpoint pointing to Edge Delta agent |
| Edge Delta agent | OTLP input node listening on the same port |
Standard ports:
- gRPC: Port
4317(no path required) - HTTP: Port
4318(paths/v1/traces,/v1/metrics,/v1/logsappended automatically)
Example: gRPC to Edge Pipeline (Kubernetes)
Configure the Java application to send to the Edge Delta agent service:
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.service.name=my-service \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.logs.exporter=otlp \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.endpoint=http://ed-data-supply-svc:4317 \
-jar yourapp.jar
Or using environment variables:
export OTEL_SERVICE_NAME="my-service"
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://ed-data-supply-svc:4317
The Edge Delta agent configuration must include an OTLP input node listening on the same port:
- name: otlp_input
type: otlp_input
port: 4317
protocol: grpc
Example: Same host (Linux VM)
When the Java application runs on the same host as the Edge Delta agent:
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
See Ingest Data from an OTLP Source for detailed Edge Delta agent configuration.
Cloud Pipeline Configuration
Use this configuration when sending telemetry directly to an Edge Delta Cloud Pipeline without a local Edge Delta agent. Cloud Pipelines are hosted by Edge Delta and expose public endpoints for data ingestion.
Key differences from Edge Pipeline:
- HTTPS required: Cloud Pipelines use TLS encryption on port
443 - Protocol must be explicit: The Java agent defaults to
http/protobuf, so you must set the protocol to match your endpoint type - No Edge Delta agent configuration: The Cloud Pipeline is pre-configured to receive OTLP data
What you configure:
| Component | Configuration |
|---|---|
| Java application | OTLP exporter with Cloud Pipeline endpoint, protocol, and TLS |
| Cloud Pipeline | Already configured with OTLP input node (no changes needed) |
Example: gRPC to Cloud Pipeline (Recommended)
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.service.name=my-service \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.logs.exporter=otlp \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.endpoint=https://pipeline-id-grpc-us-west2-cf.aws.edgedelta.com:443 \
-jar yourapp.jar
Or using environment variables:
export OTEL_SERVICE_NAME="my-service"
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=https://pipeline-id-grpc-us-west2-cf.aws.edgedelta.com:443
Replace pipeline-id-grpc-us-west2-cf.aws.edgedelta.com with your Cloud Pipeline’s gRPC endpoint from the Pipeline Settings page.
Important: You must set
-Dotel.exporter.otlp.protocol=grpcwhen using a gRPC endpoint. Without this setting, the Java agent defaults to HTTP protocol, which causes HTTP 415 (Unsupported Media Type) errors.
Example: HTTP to Cloud Pipeline
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.service.name=my-service \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.logs.exporter=otlp \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.exporter.otlp.endpoint=https://pipeline-id-http-us-west2-cf.aws.edgedelta.com:443 \
-jar yourapp.jar
Or using environment variables:
export OTEL_SERVICE_NAME="my-service"
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=https://pipeline-id-http-us-west2-cf.aws.edgedelta.com:443
Replace pipeline-id-http-us-west2-cf.aws.edgedelta.com with your Cloud Pipeline’s HTTP endpoint from the Pipeline Settings page.
Finding your Cloud Pipeline endpoints:
- Navigate to Pipelines in the Edge Delta UI
- Select your Cloud Pipeline
- Click Settings
- Copy the GRPCS Endpoint or HTTPS Endpoint
Note: The UI displays endpoints with the
grpcs://prefix (for example,grpcs://pipeline-id-grpc-...). For the Java agent, replacegrpcs://withhttps://when configuring your endpoint. Thegrpcs://scheme is not recognized by the Java agent.
Configuration Summary
| Scenario | Protocol Setting | Endpoint Format | Port |
|---|---|---|---|
| Edge Pipeline (gRPC) | grpc | http://host:4317 | 4317 |
| Edge Pipeline (HTTP) | http/protobuf | http://host:4318 | 4318 |
| Cloud Pipeline (gRPC) | grpc | https://...-grpc-...:443 | 443 |
| Cloud Pipeline (HTTP) | http/protobuf | https://...-http-...:443 | 443 |
See Cloud Pipelines for more information on Cloud Pipeline configuration and endpoints.
Explore Supported Libraries and Frameworks
The OpenTelemetry Java agent comes with built-in instrumentation for a wide array of popular libraries and frameworks. This automatic instrumentation can capture telemetry for operations such as HTTP requests, database activities, messaging systems, and more, without any need for code changes. See the available libraries and frameworks. Check that the versions of the libraries or frameworks you are using in your Java application are supported by the OpenTelemetry Java agent version you have downloaded.
Samplers
Optionally, you can include samplers in your instrumentation, for example to reduce trace data volume. You configure sampling by setting the otel.traces.sampler environment variable or JVM system property.
This example samples 10% of traces.
-Dotel.traces.sampler=traceidratio \
-Dotel.traces.sampler.arg=0.1 \
Or, using the Environment Variable approach:
export OTEL_TRACES_SAMPLER="traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"
ParentBased + Ratio-Based Sampling (Recommended for distributed tracing)
-Dotel.traces.sampler=parentbased_traceidratio
-Dotel.traces.sampler.arg=0.05 # 5% sample rate for new traces
Or, using the Environment Variable approach:
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1" # Sample 10% for new root traces
This ensures that:
- New traces (requests with no parent trace) are sampled at a fixed rate.
- Child spans (requests that belong to an existing trace) inherit their parent’s decision
Run and Verify Instrumentation
Run your Java application using the startup command configured with the OpenTelemetry Java agent.
Example: Edge Pipeline with gRPC
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.service.name=my-service \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.logs.exporter=otlp \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.endpoint=http://ed-data-supply-svc:4317 \
-Dotel.traces.sampler=parentbased_traceidratio \
-Dotel.traces.sampler.arg=0.05 \
-jar yourapp.jar
Example: Cloud Pipeline with gRPC
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.service.name=my-service \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.logs.exporter=otlp \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.endpoint=https://pipeline-id-grpc-us-west2-cf.aws.edgedelta.com:443 \
-Dotel.traces.sampler=parentbased_traceidratio \
-Dotel.traces.sampler.arg=0.05 \
-jar yourapp.jar
Environment Variables Approach
Alternatively, set environment variables and run the application:
java -jar yourapp.jar
Verify telemetry export:
- Check application logs and OpenTelemetry debug logs (enable with
-Dotel.javaagent.debug=true) for export errors - In Edge Delta, navigate to your pipeline and verify telemetry data is being received
- Look for your service name in traces, metrics, and logs
- Generate test traffic to confirm instrumentation is capturing expected operations