# OpenTelemetry for Java (the Java agent)

> Attach the OpenTelemetry Java agent with -javaagent and no code changes: HTTP servers and clients, JDBC, java.util.logging/Logback/Log4j logs; Spring Boot and containers.

The OpenTelemetry Java agent instruments a JVM app without code changes: HTTP servers and clients (Servlet, Spring MVC and WebFlux, JAX-RS, the JDK's own `HttpServer` and `HttpClient`, OkHttp, …), JDBC, messaging clients, and the common logging libraries. It reads the [standard variables](https://belvador.dev/en/docs/otel/quickstart#2-set-the-standard-variables) — its default protocol is already `http/protobuf`.

> **Tested on 2026-10-24** with java 21.0.12.1, opentelemetry-javaagent 2.32.0: traces passed, logs passed, logs carry the request's trace and span.

## Attach the agent

```bash
curl -fsSLO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
java -javaagent:./opentelemetry-javaagent.jar -jar app.jar
```

`latest` follows new releases; for production, download a fixed version from the [release page](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases) and keep it with your build, so a deploy never changes the agent by surprise.

- Start a compiled app (`-jar`, or `-cp … Main`). The agent refuses to start inside JDK tools, which includes running a source file directly with `java App.java`.
- **Spring Boot:** the same `-javaagent` flag in front of `-jar app.jar`.
- **Containers and PaaS:** when you cannot change the command, set `JAVA_TOOL_OPTIONS="-javaagent:/path/to/opentelemetry-javaagent.jar"`; the JVM picks it up on start.

## Logs

The agent captures `java.util.logging`, Logback and Log4j 2 records and sends them as OpenTelemetry log records with the active trace id and span id; your appenders keep writing as before. Belvador's run uses `java.util.logging`; Logback and Log4j 2 go through the same agent mechanism but are not part of what is marked tested.

## Turning instrumentations off

Each instrumentation has a switch, for example:

```bash
export OTEL_INSTRUMENTATION_JDBC_ENABLED=false
```

## With Sentry's Java SDK

Keep the Sentry SDK for errors with its tracing off, so the agent is the [only tracing owner](https://belvador.dev/en/docs/otel/overview#one-tracing-owner). The `sentry-opentelemetry-otlp` event processor puts the agent's span ids on those errors — see [With Sentry SDKs](https://belvador.dev/en/docs/otel/sentry-coexistence#java-sentry-java); that link is not marked tested yet.
