cd /news/developer-tools/tomcat-opentelemetry-instrumentation… · home topics developer-tools article
[ARTICLE · art-37377] src=signoz.io ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Tomcat OpenTelemetry Instrumentation Guide

SigNoz released a guide for instrumenting Apache Tomcat with OpenTelemetry to send traces to its observability platform. The guide covers setup via setenv.sh on Linux/Windows, Docker, and Kubernetes, requiring the OpenTelemetry Java agent and SigNoz ingestion keys. This enables developers to monitor Tomcat applications with distributed tracing.

read7 min views1 publishedJun 23, 2026

This guide shows how to instrument your Apache Tomcat application server with OpenTelemetry and send traces to SigNoz. Tomcat uses setenv.sh

(Linux/Mac) or setenv.bat

(Windows) to configure JVM options, making it straightforward to attach the OpenTelemetry Java agent.

Prerequisites

Java 8+ - Supported Tomcat version - A SigNoz Cloud account or self-hosted SigNoz instance

Send traces to SigNoz

Step 1. Download the OpenTelemetry Java agent to your Tomcat directory

wget -P /opt/tomcat/lib/ https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar

Replace /opt/tomcat

with your actual $CATALINA_HOME

path if different.

Step 2. Create setenv.sh in Tomcat's bin folder

Create a file at $CATALINA_HOME/bin/setenv.sh

with the following contents:

export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/tomcat/lib/opentelemetry-javaagent.jar"
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"

Make the script executable:

chmod +x $CATALINA_HOME/bin/setenv.sh

Verify these values:

<region>

: YourSigNoz Cloud region<your-ingestion-key>

: Your SigNozingestion key.<service-name>

: A descriptive name for your service (e.g.,tomcat-app

).<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. Restart Tomcat

$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh

Or if using systemd:

sudo systemctl restart tomcat

Step 1. Create a Dockerfile with the OpenTelemetry agent

FROM tomcat:10-jdk17

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

RUN echo 'export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/usr/local/tomcat/lib/opentelemetry-javaagent.jar"' > /usr/local/tomcat/bin/setenv.sh && \
    chmod +x /usr/local/tomcat/bin/setenv.sh

COPY target/*.war /usr/local/tomcat/webapps/

EXPOSE 8080
CMD ["catalina.sh", "run"]

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>

: YourSigNoz Cloud region<your-ingestion-key>

: Your SigNozingestion key.<service-name>

: A descriptive name for your service (e.g.,tomcat-app

).<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 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.

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

Apply the instrumentation:

kubectl apply -f instrumentation.yaml

Step 3. Add annotations to your Tomcat deployment

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

:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tomcat-app
  template:
    metadata:
      labels:
        app: tomcat-app
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
        resource.opentelemetry.io/service.name: "<service-name>"
        resource.opentelemetry.io/service.version: "<service-version>"
    spec:
      containers:
      - name: tomcat
        image: tomcat:10-jdk17
        ports:
        - containerPort: 8080

Apply the deployment:

kubectl apply -f deployment.yaml

The operator will automatically inject the Java agent into your Tomcat pods.

Verify these values:

<service-name>

: A descriptive name for your service (e.g.,tomcat-app

).<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 "C:\tomcat\lib\opentelemetry-javaagent.jar"

Replace C:\tomcat

with your actual Tomcat installation path.

Step 2. Create setenv.bat in Tomcat's bin folder

Create a file at %CATALINA_HOME%\bin\setenv.bat

with the following contents:

set "CATALINA_OPTS=%CATALINA_OPTS% -javaagent:C:\tomcat\lib\opentelemetry-javaagent.jar"
set "OTEL_RESOURCE_ATTRIBUTES=service.name=<service-name>,service.version=<service-version>"
set "OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.<region>.signoz.cloud:443"
set "OTEL_EXPORTER_OTLP_HEADERS=signoz-ingestion-key=<your-ingestion-key>"
set "OTEL_METRICS_EXPORTER=none"
set "OTEL_LOGS_EXPORTER=none"

Verify these values:

<region>

: YourSigNoz Cloud region<your-ingestion-key>

: Your SigNozingestion key.<service-name>

: A descriptive name for your service (e.g.,tomcat-app

).<service-version>

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

,a01dbef8

).- Update the agent path if your Tomcat is installed elsewhere.

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. Restart Tomcat

Using the command prompt:

%CATALINA_HOME%\bin\shutdown.bat
%CATALINA_HOME%\bin\startup.bat

Or if running as a Windows service:

Restart-Service Tomcat10

Step 1. Create a Dockerfile

FROM tomcat:10-jdk17

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

RUN echo 'export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/usr/local/tomcat/lib/opentelemetry-javaagent.jar"' > /usr/local/tomcat/bin/setenv.sh && \
    chmod +x /usr/local/tomcat/bin/setenv.sh

COPY target/*.war /usr/local/tomcat/webapps/

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"

EXPOSE 8080
CMD ["catalina.sh", "run"]

Verify these values:

<region>

: YourSigNoz Cloud region.<your-ingestion-key>

: Your SigNozingestion key.<service-name>

: A descriptive name for your service (e.g.,tomcat-app

).<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-tomcat-app .
docker run -p 8080:8080 my-tomcat-app

Or pass environment variables at runtime to avoid hardcoding credentials:

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

Validate

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

  • Make a few requests to your deployed web applications.
  • In SigNoz, open the Services tab and clickRefresh. Your service should appear. - Go to the Traces tab to see your application's traces.

Troubleshooting

Troubleshooting

Traces not showing up in SigNoz?

Check that setenv.sh/setenv.bat is being loaded:

Add a debug line to your setenv script:

echo "setenv.sh is being loaded" >> /tmp/tomcat-debug.log

Then restart Tomcat and check if the log file was created.

Verify the agent is attached:

Check your Tomcat logs (catalina.out

) for OpenTelemetry startup messages:

[otel.javaagent] opentelemetry-javaagent - version: X.X.X

Enable debug logging:

Add to your setenv.sh:

export OTEL_LOG_LEVEL=debug

Look for span output in Tomcat's logs. 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?

Check file permissions:

ls -la /opt/tomcat/lib/opentelemetry-javaagent.jar

The Tomcat user must have read access to the agent JAR.

Verify CATALINA_HOME:

echo $CATALINA_HOME

Make sure your setenv.sh is in the correct bin

directory.

setenv.sh not found or not executed?

On some Linux distributions, Tomcat may be configured differently. Check:

  • The file is named exactly setenv.sh

(case-sensitive) - The file is in $CATALINA_HOME/bin/

or$CATALINA_BASE/bin/

  • The file has execute permissions: chmod +x setenv.sh

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

Add these to your CATALINA_OPTS

in setenv.sh:

Disable specific instrumentations:

export CATALINA_OPTS="$CATALINA_OPTS -Dotel.instrumentation.jdbc-datasource.enabled=false"

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-tomcat-app,deployment.environment=production,service.version=1.2.3"

See the full configuration reference for all available options.

Next steps

Add manual instrumentationfor custom spans and business contextCollect Java application logswith OpenTelemetrySet up alertsfor your Tomcat application

── more in #developer-tools 4 stories · sorted by recency
── more on @apache tomcat 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/tomcat-opentelemetry…] indexed:0 read:7min 2026-06-23 ·