This Quick Start guide shows you how to configure your Java applications to send OpenTelemetry traces to Cloud Observability.
This guide does not provide documentation on application instrumentation. For Java-specific information on instrumentation, please see the Java OpenTelemetry getting started guide.
The sections below contain code snippets only. For full code listings, please see java/otlp
and java/launcher
in the Cloud Observability OpenTelemetry examples repository.
Sending OpenTelemetry data directly to Cloud Observability without a Collector for most developer setups will suffice. For non-development setups, however, it is highly recommended that you send OpenTelemetry data to Cloud Observability by way of the OpenTelemetry Collector. This can be done with or without a Launcher, as we’ll see below.
Before you get started with sending OpenTelemetry data to Cloud Observability, you will need the following:
In your application code, you will need to install dependencies and import OpenTelemetry packages before you can send data to Cloud Observability.
Start by installing the Java auto-instrumentation agent. Do this by opening up a terminal window and pasting the following:
1
curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
You will also need to add the following OpenTelemetry dependencies to your
pom.xml
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
<dependencies>
...
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.18.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-annotations</artifactId>
<version>1.18.0-alpha</version>
</dependency>
...
</dependencies>
...
You can find the latest version of the OpenTelemetry Java here.
If you are using Gradle, your dependencies in build.gradle
would look like
this:
1
2
3
4
5
6
7
8
...
dependencies {
...
implementation("io.opentelemetry:opentelemetry-api:1.18.0")
implementation("io.opentelemetry:opentelemetry-instrumentation-annotations:1.18.0")
...
}
...
Although auto-instrumentation is a great way to get started quickly with instrumenting your Java application, it is often not sufficient. In order to gain greater insights into your application code, you should also add manual instrumentation to your business logic. More on auto-instrumentation vs manual instrumentation here.
In order to manually instrument your Java code, you need to acquire a Tracer. The Tracer is responsible for creating Spans and interacting with the Context.
Before you can acquire a Tracer, you must first import the appropriate package. Open up your application code, and add the following import to your .java
file:
1
import io.opentelemetry.api;
Now you are ready to acquire your tracer. This should be declared as a private, class-level variable so that it can be easily accessed by other methods in your class.
1
2
3
4
5
6
...
public class MyClass {
...
private static final Tracer tracer = GlobalOpenTelemetry.getTracer("CloudObsExample");
...
}
Where CloudObsExample
can be replaced by anything. More info
here.
The Java auto-instrumentation agent is used to configure OpenTelemetry and auto-instrument your code. It dynamically injects bytecode to capture telemetry from many popular libraries and frameworks. A full list of auto-instrumented Java libraries can be found here.
Start tabs
Direct (gRPC)
1
2
3
4
5
6
7
8
9
10
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="lightstep-access-token=<LS_ACCESS_TOKEN>"
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=<service_name> \
-Dotel.traces.exporter=logging,otlp \
-Dotel.metrics.exporter=logging,otlp \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.endpoint="https://ingest.lightstep.com:443" ## US data center \
## -Dotel.exporter.otlp.endpoint="https://ingest.eu.lightstep.com:443" ## EU data center \
-jar path/to/your/app.jar
Collector (gRPC)
1
2
3
4
5
6
7
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=<service_name> \
-Dotel.traces.exporter=logging,otlp \
-Dotel.metrics.exporter=logging,otlp \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.endpoint="http://0.0.0.0:4317" \
-jar path/to/your/app.jar
End tabs
To view traces in your Cloud Observability project, click explorer in the left navigation bar, and then click on any span in the Trace Analysis table.
<LS_ACCESS_TOKEN>
with your own Cloud Observability access token.otel.service.name
sets the name of the service. This is the value that will
show up in the Cloud Observability service explorer. Be sure to
replace <service_name>
with your own service name.otel.traces.exporter
and otel.metrics.exporter
specify where to send
traces and metrics, respectively. In this case, they are being sent to the
console
(stdout) and to otlp
. The otlp
option tells the Java agent to
send it to an endpoint that accepts OTLP. More information can be found
here.otel.exporter.otlp.protocol
specifies whether to send OTLP requests via gRPC
or HTTP.otel.exporter.otlp.endpoint
specifies where to send the traces and metrics
to OTLP endpoint https://ingest.lightstep.com:443
(i.e. Cloud Observability).
Organizations using the EU data center should use ingest.eu.lightstep.com:443
.
Include the https://
prefix for the gRPC endpoint,
otherwise, you will get an error.
To use HTTP instead of gRPC, update the call to the Java agent as follows:
1
2
3
4
5
6
7
8
9
10
11
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=<service_name> \
-Dotel.traces.exporter=logging,otlp \
-Dotel.metrics.exporter=logging,otlp \
-Dotel.exporter.otlp.traces.protocol=http/protobuf \
-Dotel.exporter.otlp.metrcs.protocol=grpc \
-Dotel.exporter.otlp.traces.endpoint="https://ingest.lightstep.com/traces/otlp/v0.9" \ #US data center
-Dotel.exporter.otlp.metrics.endpoint="https://ingest.lightstep.com:443" \ #US data center
#-Dotel.exporter.otlp.traces.endpoint="https://ingest.eu.lightstep.com/traces/otlp/v0.9" \ ## EU data center
#-Dotel.exporter.otlp.metrics.endpoint="https://ingest.eu.lightstep.com:443" \ ## EU data center
-jar path/to/your/app.jar
Noteworthy items:
https://ingest.lightstep.com/traces/otlp/v0.9
instead of https://ingest.lightstep.com:443
(https://ingest.eu.lightstep.com/traces/otlp/v0.9
for the EU data center).otel.traces.exporter
uses http/protobuf
instead of grpc
.otel.exporter.otlp.endpoint
for both. Instead, in this example, we must
define separate endpoints for traces (via HTTP) and metrics (via gRPC).OTEL_EXPORTER_OTLP_TRACES_HEADERS
environment variable,
because the LS_ACCESS_TOKEN
is already configured in the Collector’s
config.yml
file.otel.exporter.otlp.endpoint
option is left out, the agent assumes
that you have a Collector running locally at http://0.0.0.0:4317
. If you
wish to use a different Collector endpoint, simply include the
otel.exporter.otlp.endpoint
option with your Collector’s gRPC endtpoint.otel.service.name
sets the name of the service. This is the value that will
show up in the Cloud Observability service explorer. Be sure to
replace <service_name>
with your own service name.To use HTTP instead of gRPC, update the call to the Java agent as follows:
1
2
3
4
5
6
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=java-collector-server-http \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.exporter.otlp.protocol=http/protobuf \
-jar target/lightstep-otlp-server.jar com.lightstep.otlp.server.ExampleServer
Which is the equivalent of:
1
2
3
4
5
6
7
8
9
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=java-collector-server-http \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=otlp \
-Dotel.exporter.otlp.traces.protocol=http/protobuf \
-Dotel.exporter.otlp.metrics.protocol=http/protobuf \
-Dotel.exporter.otlp.traces.endpoint="http://0.0.0.0:4318/v1/traces" \
-Dotel.exporter.otlp.metrics.endpoint="http://0.0.0.0:4318/v1/metrics" \
-jar target/lightstep-otlp-server.jar com.lightstep.otlp.server.ExampleServer
Noteworthy items:
otel.exporter.otlp.protocol
uses http/protobuf
instead of grpc
.otel.exporter.otlp.endpoint
is omitted when using HTTP, it is the
equivalent of saying
-Dotel.exporter.otlp.traces.endpoint="http://0.0.0.0:4318/v1/traces"
and
-Dotel.exporter.otlp.metrics.endpoint="http://0.0.0.0:4318/v1/metrics"
otel.exporter.otlp.protocol=http/protobuf
is the equivalent of saying
otel.exporter.otlp.traces.protocol=http/protobuf
and
otel.exporter.otlp.metrics.protocol=http/protobuf
otel.exporter.otlp.traces.endpoint
)
and metrics (otel.exporter.otlp.metrics.endpoint
). You will also need to
include the /v1/traces
suffix for traces, and the /v1/metrics
for metrics
as part of the endpoint.Noteworthy items:
LS_ACCESS_TOKEN
, since that’s already configured in the
Collector’s
config.yml
file.otel.exporter.otlp.endpoint
to send traces to a
Collector, the traces will be sent directly to ingest.lightstep.com:443
(or ingest.eu.lightstep.com:443
for the EU)
instead of via the Collector. Instead, you need to override
otel.exporter.otlp.traces.endpoint
for traces, and
otel.exporter.otlp.metrics.endpoint
for metrics.otel.exporter.otlp.traces.endpoint
and
otel.exporter.otlp.metrics.endpoint
, using your own Collector’s endpoint./v1/traces
suffix for traces, and the /v1/metrics
for metrics
as part of the endpoint.To see Java agent debug logs, you can pass in -Dotel.javaagent.debug=true
:
1
2
3
4
java -javaagent:opentelemetry-javaagent.jar \
...
-Dotel.javaagent.debug=true
...
Note that these are quite verbose.
If you are having trouble sending traces to your endpoint (whether it is to Cloud Observability or to your Collector, please ensure that you include the http://
or https://
prefix for your endpoints, otherwise the Java agent will err out.
If you choose to use the OpenTelemetry Collector over HTTP, your endpoint will need to include the /v1/{signal}
suffix. You will also need to ensure that you set otel.exporter.otlp.traces.protocol
to http/protobuf
. For example:
1
2
3
4
5
6
7
8
9
10
java -javaagent:opentelemetry-javaagent.jar \
...
# Traces
-Dotel.exporter.otlp.traces.protocol=http/protobuf \
-Dotel.exporter.otlp.traces.endpoint="http://0.0.0.0:4318/v1/traces" \
# Metrics
-Dotel.exporter.otlp.metrics.protocol=http/protobuf \
-Dotel.exporter.otlp.metrics.endpoint="http://0.0.0.0:4318/v1/metrics" \
...
For more information, and configuration options please see Java agent OpenTelemetry documentation.
If multiple versions of OpenTelemetry are installed, traces are not created or propagated correctly. Check your dependencies to ensure that only a single version of OpenTelemetry is installed.
Cloud Observability’s public Microsatellites only accept spans via a secure endpoint. If you see security related errors (e.g., Netty TLS errors with Java), you may not have the necessary root certificate installed on the machine where the tracer is running. To add a root certificate, see the documentation about encrypted connections.
Not seeing metrics come through the OpenTelemetry Collector? Make sure that you have defined a Metrics pipeline in your Collector’s YAML config file.
Send traces to Cloud Observability with Python
Send traces to Cloud Observability with Go
Send traces to Cloud Observability with .NET
Updated May 19, 2023