# Java & Spring Boot OpenTelemetry Setup Guide

> Source: <https://signoz.io/docs/instrumentation/java/opentelemetry-java>
> Published: 2026-06-17 00:00:00+00:00

This guide walks you through instrumenting your Java or Spring Boot application with OpenTelemetry and sending traces to SigNoz. The Java agent handles most popular libraries and frameworks automatically—Spring, JDBC, HTTP clients, message queues, and more.

Prerequisites

[Java 8+](https://github.com/open-telemetry/opentelemetry-java#requirements)- A SigNoz Cloud account or self-hosted SigNoz instance

Send traces to SigNoz

Step 1. Download the OpenTelemetry Java agent

```
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
```

Step 2. Set environment variables

```
export OTEL_RESOURCE_ATTRIBUTES="service.name=<service-name>,service.version=<service-version>"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
export OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"
```

Verify these values:

`<region>`

: Your[SigNoz Cloud region](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint).`<your-ingestion-key>`

: Your SigNoz[ingestion key](https://signoz.io/docs/ingestion/signoz-cloud/keys/).`<service-name>`

: A descriptive name for your service (e.g.,`payment-service`

).`<service-version>`

(optional): Your release version, image tag, or git SHA (e.g.,`1.4.2`

,`a01dbef8`

).

Set `service.version`

to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

**Bash / shell**:`service.version=$(git rev-parse --short HEAD)`

**GitHub Actions**:`service.version=${{ github.sha }}`

**GitLab CI**:`service.version=$CI_COMMIT_SHORT_SHA`

**Kubernetes**: inject from your Helm chart image tag or CI variable

Step 3. Run your application

For Spring Boot applications:

```
java -javaagent:./opentelemetry-javaagent.jar -jar your-app.jar
```

For generic Java applications, you can also pass config as system properties:

```
java -javaagent:./opentelemetry-javaagent.jar \
  -Dotel.service.name=my-service \
  -Dotel.exporter.otlp.endpoint=https://ingest.us.signoz.cloud:443 \
  -Dotel.exporter.otlp.headers=signoz-ingestion-key=<key> \
  -jar your-app.jar
```

Step 1. Add the agent to your Dockerfile

```
FROM eclipse-temurin:17-jre
WORKDIR /app

COPY target/<my-app>.jar app.jar

RUN wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar -O opentelemetry-javaagent.jar

ENTRYPOINT ["java", "-javaagent:/app/opentelemetry-javaagent.jar", "-jar", "app.jar"]
```

Step 2. Deploy to Kubernetes

Add these environment variables to your deployment manifest:

```
env:
- name: OTEL_RESOURCE_ATTRIBUTES
  value: 'service.name=<service-name>,service.version=<service-version>'
- name: OTEL_EXPORTER_OTLP_ENDPOINT
  value: 'https://ingest.<region>.signoz.cloud:443'
- name: OTEL_EXPORTER_OTLP_HEADERS
  value: 'signoz-ingestion-key=<your-ingestion-key>'
- name: OTEL_METRICS_EXPORTER
  value: 'none'
- name: OTEL_LOGS_EXPORTER
  value: 'none'
```

Verify these values:

`<region>`

: Your[SigNoz Cloud region](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint).`<your-ingestion-key>`

: Your SigNoz[ingestion key](https://signoz.io/docs/ingestion/signoz-cloud/keys/).`<service-name>`

: A descriptive name for your service (e.g.,`payment-service`

).`<service-version>`

(optional): Your release version, image tag, or git SHA (e.g.,`1.4.2`

,`a01dbef8`

).

Set `service.version`

to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

**Bash / shell**:`service.version=$(git rev-parse --short HEAD)`

**GitHub Actions**:`service.version=${{ github.sha }}`

**GitLab CI**:`service.version=$CI_COMMIT_SHORT_SHA`

**Kubernetes**: inject from your Helm chart image tag or CI variable

The [OpenTelemetry Operator](https://signoz.io/docs/opentelemetry-collection-agents/k8s/otel-operator/overview/) auto-injects the Java agent into your pods without modifying your container image.

Step 1. Set up the OpenTelemetry Operator

Install the Operator and Collector following the [K8s OTel Operator installation guide](https://signoz.io/docs/opentelemetry-collection-agents/k8s/otel-operator/install/).

Step 2. Create the Instrumentation resource

Create `instrumentation.yaml`

to configure Java auto-instrumentation:

```
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: java-instrumentation
spec:
  exporter:
    endpoint: http://otel-collector-collector:4318
  propagators:
    - tracecontext
    - baggage
  env:
    - name: OTEL_METRICS_EXPORTER
      value: "none"
    - name: OTEL_LOGS_EXPORTER
      value: "none"
  java:
    image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:latest
```

Deploy this resource to your cluster.

Step 3. Add annotations to your deployment

Add these annotations to your pod template's `metadata.annotations`

:

```
instrumentation.opentelemetry.io/inject-java: "true"
resource.opentelemetry.io/service.name: "<service-name>"
resource.opentelemetry.io/service.version: "<service-version>"
```

Verify these values:

`<service-name>`

: A descriptive name for your service (e.g.,`payment-service`

).`<service-version>`

(optional): Your release version, image tag, or git SHA (e.g.,`1.4.2`

,`a01dbef8`

).

Set `service.version`

to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

**Bash / shell**:`service.version=$(git rev-parse --short HEAD)`

**GitHub Actions**:`service.version=${{ github.sha }}`

**GitLab CI**:`service.version=$CI_COMMIT_SHORT_SHA`

**Kubernetes**: inject from your Helm chart image tag or CI variable

Step 1. Download the OpenTelemetry Java agent

```
Invoke-WebRequest -Uri "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar" -OutFile "opentelemetry-javaagent.jar"
```

Step 2. Set environment variables

```
$env:OTEL_RESOURCE_ATTRIBUTES = "service.name=<service-name>,service.version=<service-version>"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://ingest.<region>.signoz.cloud:443"
$env:OTEL_EXPORTER_OTLP_HEADERS = "signoz-ingestion-key=<your-ingestion-key>"
$env:OTEL_METRICS_EXPORTER = "none"
$env:OTEL_LOGS_EXPORTER = "none"
```

Verify these values:

`<region>`

: Your[SigNoz Cloud region](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint).`<your-ingestion-key>`

: Your SigNoz[ingestion key](https://signoz.io/docs/ingestion/signoz-cloud/keys/).`<service-name>`

: A descriptive name for your service (e.g.,`payment-service`

).`<service-version>`

(optional): Your release version, image tag, or git SHA (e.g.,`1.4.2`

,`a01dbef8`

).

Set `service.version`

to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

**Bash / shell**:`service.version=$(git rev-parse --short HEAD)`

**GitHub Actions**:`service.version=${{ github.sha }}`

**GitLab CI**:`service.version=$CI_COMMIT_SHORT_SHA`

**Kubernetes**: inject from your Helm chart image tag or CI variable

Step 3. Run your application

For Spring Boot applications:

```
java -javaagent:.\opentelemetry-javaagent.jar -jar your-app.jar
```

For generic Java applications, you can also pass config as system properties:

```
java -javaagent:.\opentelemetry-javaagent.jar `
  -Dotel.service.name=my-service `
  -Dotel.exporter.otlp.endpoint=https://ingest.us.signoz.cloud:443 `
  -Dotel.exporter.otlp.headers=signoz-ingestion-key=<key> `
  -jar your-app.jar
```

Step 1. Add the agent to your Dockerfile

```
FROM eclipse-temurin:17-jre
WORKDIR /app

COPY target/<my-app>.jar app.jar

RUN wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar -O opentelemetry-javaagent.jar

ENV OTEL_RESOURCE_ATTRIBUTES="service.name=<service-name>,service.version=<service-version>"
ENV OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.signoz.cloud:443"
ENV OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<your-ingestion-key>"
ENV OTEL_METRICS_EXPORTER="none"
ENV OTEL_LOGS_EXPORTER="none"

ENTRYPOINT ["java", "-javaagent:/app/opentelemetry-javaagent.jar", "-jar", "app.jar"]
```

Verify these values:

`<region>`

: Your[SigNoz Cloud region](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint).`<your-ingestion-key>`

: Your SigNoz[ingestion key](https://signoz.io/docs/ingestion/signoz-cloud/keys/).`<service-name>`

: A descriptive name for your service (e.g.,`payment-service`

).`<service-version>`

(optional): Your release version, image tag, or git SHA (e.g.,`1.4.2`

,`a01dbef8`

).

Set `service.version`

to a per-build value, not a static string. SigNoz detects a deployment each time this value changes. Common sources:

**Bash / shell**:`service.version=$(git rev-parse --short HEAD)`

**GitHub Actions**:`service.version=${{ github.sha }}`

**GitLab CI**:`service.version=$CI_COMMIT_SHORT_SHA`

**Kubernetes**: inject from your Helm chart image tag or CI variable

Step 2. Build and run

```
docker build -t my-java-app .
docker run -p 8080:8080 my-java-app
```

Or pass environment variables at runtime:

```
docker run -p 8080:8080 \
  -e OTEL_RESOURCE_ATTRIBUTES="service.name=my-service" \
  -e OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.us.signoz.cloud:443" \
  -e OTEL_EXPORTER_OTLP_HEADERS="signoz-ingestion-key=<key>" \
  -e OTEL_METRICS_EXPORTER="none" \
  -e OTEL_LOGS_EXPORTER="none" \
  my-java-app
```

Validate

With your application running, verify traces are being sent to SigNoz:

- Make a few requests to your application endpoints.
- In SigNoz, open the
**Services** tab and click**Refresh**. Your application should appear. - Go to the
**Traces** tab to see your application's traces.

Troubleshooting

[Troubleshooting](#troubleshooting)

Traces not showing up in SigNoz?

**Check environment variables:**

```
echo $OTEL_EXPORTER_OTLP_ENDPOINT
echo $OTEL_RESOURCE_ATTRIBUTES
```

**Enable debug logging:**

```
OTEL_LOG_LEVEL=debug java -javaagent:./opentelemetry-javaagent.jar -jar app.jar
```

Look for span output in stdout. If spans appear locally but not in SigNoz, check your endpoint URL and ingestion key.

**Test connectivity:**

```
curl -v https://ingest.<region>.signoz.cloud:443/v1/traces
```

Agent not attaching?

Make sure `-javaagent`

comes before `-jar`

:

```
# Correct
java -javaagent:./agent.jar -jar app.jar

# Wrong - agent flag after -jar is ignored
java -jar app.jar -javaagent:./agent.jar
```

Configuring the agent (Optional)

[Configuring the agent (Optional)](#configuring-the-agent-optional)

What can you configure?

The Java agent auto-instruments most libraries out of the box. Configuration lets you fine-tune what gets captured and how traces are exported.

Why configure?

**Reduce noise**— Disable instrumentation for internal health checks or chatty libraries** Control costs**— Sample a percentage of traces instead of capturing everything** Add context**— Tag traces with environment, version, or team info for easier filtering

Common options

**Disable specific instrumentations:**

```
-Dotel.instrumentation.jdbc-datasource.enabled=false
```

Some instrumentations are disabled by default because they're noisy:

`jdbc-datasource`

— creates spans for every`DataSource.getConnection()`

call`dropwizard-metrics`

— limited attribute support in Dropwizard's metrics API

**Sample traces:**

```
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.1  # Sample 10% of traces
```

**Add resource attributes:**

```
export OTEL_RESOURCE_ATTRIBUTES="service.name=my-app,deployment.environment=production,service.version=1.2.3"
```

See the [full configuration reference](https://opentelemetry.io/docs/languages/java/automatic/agent-config/) for all available options.

Setup OpenTelemetry Collector (Optional)

[Setup OpenTelemetry Collector (Optional)](#setup-opentelemetry-collector-optional)

What is the OpenTelemetry Collector?

The Collector sits between your app and SigNoz. Your app sends traces to the Collector, which then forwards them to SigNoz.

Why use it?

**Filter and transform**- Drop noisy traces or redact sensitive data before it leaves your network** Reduce app overhead**- Let the Collector handle batching, retries, and compression** Add metadata**- Automatically tag traces with Kubernetes pod info, cloud region, etc.** Multi-backend**- Send to multiple observability tools without changing your app

See [Switch from direct export to Collector](https://signoz.io/docs/opentelemetry-collection-agents/opentelemetry-collector/switch-to-collector/) for setup instructions.

Next steps

[Add manual instrumentation](https://signoz.io/docs/instrumentation/java/manual-instrumentation/)for custom spans and business context- Send
[metrics](https://signoz.io/docs/metrics-management/send-metrics/applications/opentelemetry-java/)and[logs](https://signoz.io/docs/logs-management/send-logs/java-logs/)from your Java application for complete observability [Set up alerts](https://signoz.io/docs/setup-alerts-notification/)for your Java application- For a framework-focused walkthrough, our
[Spring Boot OpenTelemetry tutorial](https://signoz.io/blog/opentelemetry-spring-boot/)covers instrumentation patterns specific to Spring alongside the agent setup above.

**Sample applications**:
