Java
Send OpenTelemetry traces from Java applications to KubeSense with the OpenTelemetry Java agent.
Java applications are instrumented with the OpenTelemetry Java agent, a single JAR attached at startup. It creates spans for Spring Boot, servlet containers, JDBC, Kafka, gRPC, HTTP clients and many other libraries, with no code changes. It supports Java 8 and later.
Option 1: Kubernetes with the OpenTelemetry Operator (zero code)
If you have set up the OpenTelemetry Operator, add this annotation to the pod template and restart the workload:
spec:
template:
metadata:
annotations:
instrumentation.opentelemetry.io/inject-java: "kubesense/otel-instrumentation"Option 2: Auto-instrumentation on VMs (no code changes)
Use this on VMs, or on Kubernetes clusters without the operator. You only attach the Java agent at startup; the application code is not changed.
Step 1: Download the agent
curl -sSfL -o opentelemetry-javaagent.jar \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jarFor production, pin a specific version instead of latest. Releases are listed at opentelemetry-java-instrumentation releases.
Step 2: Start the application with the agent
Using system properties:
java -javaagent:/opt/otel/opentelemetry-javaagent.jar \
-Dotel.service.name=payments-service \
-Dotel.exporter.otlp.endpoint=http://<KUBESENSE_INGEST_HOST>:33443 \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.resource.attributes=kubesense.cluster=<CLUSTER_NAME>,kubesense.env_type=legacy \
-Dotel.metrics.exporter=none \
-Dotel.logs.exporter=none \
-jar payments-service.jarOr using environment variables, which is easier in containers:
export JAVA_TOOL_OPTIONS="-javaagent:/opt/otel/opentelemetry-javaagent.jar"
export OTEL_SERVICE_NAME=payments-service
export OTEL_EXPORTER_OTLP_ENDPOINT=http://<KUBESENSE_INGEST_HOST>:33443
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_RESOURCE_ATTRIBUTES=kubesense.cluster=<CLUSTER_NAME>,kubesense.env_type=legacy
export OTEL_METRICS_EXPORTER=none
export OTEL_LOGS_EXPORTER=none
java -jar payments-service.jar| Setting | Value | Notes |
|---|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | http://<KUBESENSE_INGEST_HOST>:33443 | Base URL only; the agent appends /v1/traces. Inside the KubeSense cluster, use http://kubesense-kubecol.kubesense.svc.cluster.local:33443 |
OTEL_EXPORTER_OTLP_PROTOCOL | http/protobuf | Port 33443 accepts OTLP over HTTP |
OTEL_RESOURCE_ATTRIBUTES | kubesense.cluster=...,kubesense.env_type=... | Use = between key and value, and , between pairs. Use kubesense.env_type=k8s on Kubernetes |
Container image (Kubernetes without the operator)
FROM eclipse-temurin:21-jre
ARG OTEL_JAVA_AGENT_VERSION=<VERSION>
ADD https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OTEL_JAVA_AGENT_VERSION}/opentelemetry-javaagent.jar /opt/otel/opentelemetry-javaagent.jar
COPY target/payments-service.jar /app/app.jar
ENV JAVA_TOOL_OPTIONS="-javaagent:/opt/otel/opentelemetry-javaagent.jar" \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=none
ENTRYPOINT ["java", "-jar", "/app/app.jar"]Set OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_RESOURCE_ATTRIBUTES in the Kubernetes manifest.
Step 3: Verify
Startup logs show a line similar to opentelemetry-javaagent - version: .... Generate some traffic, then open APM → Traces in KubeSense and filter by your service name.
Manual instrumentation (SDK)
For Spring Boot applications, you can add OpenTelemetry as a dependency instead of attaching the Java agent. The OpenTelemetry Spring Boot starter instruments Spring web requests, RestTemplate / WebClient calls, JDBC and other common libraries, and is configured with the same OTEL_* environment variables. Use it instead of the Java agent.
For applications that don't use Spring Boot, use the Java agent (Option 1 or Option 2).
Step 1: Add the dependency
Maven:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-bom</artifactId>
<version>${opentelemetry-instrumentation.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-spring-boot-starter</artifactId>
</dependency>
</dependencies>Gradle:
implementation platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:${otelInstrumentationVersion}")
implementation "io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter"Use the latest version from opentelemetry-java-instrumentation releases.
Step 2: Configure the endpoints
No setup code is needed: the starter configures itself when the application starts. Set the environment variables from Manual SDK: where to send traces, then build and start the application as usual.
Troubleshooting
Add -Dotel.javaagent.debug=true temporarily to print the agent's activity.
| Symptom | Check |
|---|---|
| No agent line in the startup logs | -javaagent must come before -jar. When using JAVA_TOOL_OPTIONS, check that the process sees the variable |
Failed to export spans / connection refused | Trace ingestion is not enabled on KubeSense, or port 33443 is not reachable |
| Resource attributes missing in KubeSense | Check the format: key=value pairs separated by commas, for example kubesense.env_type=k8s, not kubesense.env_type:k8s |
| Exporter errors for metrics or logs | Set OTEL_METRICS_EXPORTER=none and OTEL_LOGS_EXPORTER=none |
| Too many spans from one library | Disable it, for example -Dotel.instrumentation.jdbc.enabled=false. Replace jdbc with the instrumentation's name |