OpenTelemetry Tomcat: Instrumentation and Monitoring Guide

Vladimir Mihailenco
March 02, 2026
5 min read

OpenTelemetry provides automatic instrumentation for Apache Tomcat applications, enabling distributed tracing, JVM metrics collection, and servlet monitoring without code changes. Using the OpenTelemetry Java Agent, you can gain full observability into your Tomcat-hosted web applications, including request latencies, database queries, and downstream service calls.

Quick Reference

ComponentDetails
Instrumentation methodOpenTelemetry Java Agent (automatic)
Supported signalsTraces, Metrics, Logs
Code changes requiredNone (agent-based)
ConfigurationEnvironment variables in setenv.sh / setenv.bat
Libraries instrumentedServlets, JSP, JDBC, HTTP clients, JMS, and 150+ more

What is OpenTelemetry?

OpenTelemetry is an open-source observability framework that standardizes the collection of telemetry data from applications. It provides three pillars of observability:

  • Distributed Traces: Track requests across services and components
  • Metrics: Collect JVM, servlet, and application-level measurements
  • Logs: Capture structured application logs with trace correlation

OpenTelemetry is vendor-neutral, meaning you can export data to any compatible OpenTelemetry backend such as Uptrace, Jaeger, or Grafana. Configuration is managed through environment variables.

Prerequisites

  • Apache Tomcat 7.0+ (Tomcat 9 and 10 recommended)
  • Java 8+ (Java 11+ recommended for full metrics support)
  • Network access to your OTLP-compatible backend

OpenTelemetry Java Agent

The OpenTelemetry Java Agent automatically instruments Tomcat applications at the bytecode level, capturing traces for servlets, JDBC queries, HTTP clients, and 150+ libraries without code changes.

Download the latest agent JAR:

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

Place the JAR in a directory accessible by Tomcat, such as /opt/opentelemetry/ or Tomcat's lib directory.

Configuring Tomcat with OpenTelemetry

Linux / macOS

Create a setenv.sh file in Tomcat's bin directory:

shell
#!/bin/bash

# Attach the OpenTelemetry Java Agent
export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/opt/opentelemetry/opentelemetry-javaagent.jar"

# Service identification
export OTEL_RESOURCE_ATTRIBUTES=service.name=tomcat-app,service.version=1.0.0

# Enable all signal types
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp

# OTLP exporter configuration
export OTEL_EXPORTER_OTLP_COMPRESSION=gzip
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317
export OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<FIXME>"

# Recommended metrics settings
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=DELTA
export OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION=BASE2_EXPONENTIAL_BUCKET_HISTOGRAM

Make the script executable and restart Tomcat:

shell
chmod +x bin/setenv.sh
./bin/shutdown.sh && ./bin/startup.sh

Windows

Create a setenv.bat file in Tomcat's bin directory:

bat
set "CATALINA_OPTS=%CATALINA_OPTS% -javaagent:C:\opentelemetry\opentelemetry-javaagent.jar"

set OTEL_RESOURCE_ATTRIBUTES=service.name=tomcat-app,service.version=1.0.0
set OTEL_TRACES_EXPORTER=otlp
set OTEL_METRICS_EXPORTER=otlp
set OTEL_LOGS_EXPORTER=otlp
set OTEL_EXPORTER_OTLP_COMPRESSION=gzip
set OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317
set OTEL_EXPORTER_OTLP_HEADERS=uptrace-dsn=<FIXME>
set OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=DELTA
set OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION=BASE2_EXPONENTIAL_BUCKET_HISTOGRAM

Docker

For containerized Tomcat deployments, pass the agent as a JVM argument in your Dockerfile:

dockerfile
FROM tomcat:10-jdk17

# Download OpenTelemetry Java Agent
ADD https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar /opt/opentelemetry/opentelemetry-javaagent.jar

# Set environment variables
ENV CATALINA_OPTS="-javaagent:/opt/opentelemetry/opentelemetry-javaagent.jar"
ENV OTEL_RESOURCE_ATTRIBUTES="service.name=tomcat-app,service.version=1.0.0"
ENV OTEL_TRACES_EXPORTER="otlp"
ENV OTEL_METRICS_EXPORTER="otlp"
ENV OTEL_LOGS_EXPORTER="otlp"
ENV OTEL_EXPORTER_OTLP_COMPRESSION="gzip"

# Deploy your application
COPY target/myapp.war /usr/local/tomcat/webapps/

Build and run:

shell
docker build -t tomcat-otel .
docker run -p 8080:8080 \
  -e OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317 \
  -e OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<FIXME>" \
  tomcat-otel

For a complete Docker Compose setup with the OpenTelemetry Collector, see the Docker deployment guide.

Verifying the Installation

After restarting Tomcat, verify the agent is attached by checking the Tomcat logs:

shell
tail -f logs/catalina.out | grep -i opentelemetry

You should see output similar to:

text
[otel.javaagent] opentelemetry-javaagent - version: 2.x.x
[otel.javaagent] Installed instrumentation: servlet-5.0 [io.opentelemetry.javaagent]
[otel.javaagent] Installed instrumentation: tomcat-10.0 [io.opentelemetry.javaagent]

You can also verify from a running process:

shell
ps aux | grep javaagent

What Gets Instrumented Automatically

The Java Agent instruments these Tomcat components without code changes:

ComponentCaptured Data
HTTP ServletsRequest method, URL, status code, latency
JSP PagesRendering time, template name
JDBCDatabase queries, connection pool metrics
HTTP ClientsOutgoing requests (HttpURLConnection, Apache HttpClient)
JMSMessage queue operations
JMX MetricsJVM memory, GC, thread counts, CPU usage

Custom Instrumentation

For application-specific tracing beyond automatic instrumentation, add the OpenTelemetry API to your project.

Add the dependency to pom.xml:

xml
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    <version>1.44.1</version>
</dependency>

Create custom spans in your servlets:

java
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import jakarta.servlet.http.*;

public class OrderServlet extends HttpServlet {
    private static final Tracer tracer =
        GlobalOpenTelemetry.getTracer("com.example.orders");

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        Span span = tracer.spanBuilder("process-order").startSpan();
        try (var scope = span.makeCurrent()) {
            String orderId = req.getParameter("orderId");
            span.setAttribute("order.id", orderId);

            // Your business logic
            processOrder(orderId);

            span.setAttribute("order.status", "completed");
        } catch (Exception e) {
            span.recordException(e);
            span.setStatus(io.opentelemetry.api.trace.StatusCode.ERROR, e.getMessage());
            resp.setStatus(500);
        } finally {
            span.end();
        }
    }
}

For comprehensive Java instrumentation, see the OpenTelemetry Java guide.

Environment Variables Reference

Common environment variables for tuning the Java Agent with Tomcat:

VariableDescriptionExample Value
OTEL_SERVICE_NAMEService nametomcat-app
OTEL_EXPORTER_OTLP_ENDPOINTOTLP collector endpointhttps://api.uptrace.dev:4317
OTEL_EXPORTER_OTLP_HEADERSAuthentication headersuptrace-dsn=<FIXME>
OTEL_TRACES_SAMPLERSampling strategyparentbased_traceidratio
OTEL_TRACES_SAMPLER_ARGSampling ratio (0.0 to 1.0)0.1
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUESTCapture request headerscontent-type,x-request-id
OTEL_JAVAAGENT_DEBUGEnable debug loggingtrue

For the full list of environment variables, see the OpenTelemetry environment variables reference.

Troubleshooting

Agent not loading: Verify the -javaagent path is correct and the JAR file is readable by the Tomcat process user. Check catalina.out for errors.

No traces appearing: Confirm OTEL_EXPORTER_OTLP_ENDPOINT is reachable from the Tomcat server. Test connectivity:

shell
curl -v https://api.uptrace.dev:4317

High memory usage: Reduce the export batch size and queue:

shell
export OTEL_BSP_MAX_QUEUE_SIZE=512
export OTEL_BSP_MAX_EXPORT_BATCH_SIZE=128

Startup performance: The agent adds 100-300ms to startup. For faster startup in development, disable unused instrumentations:

shell
export OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED=false
export OTEL_INSTRUMENTATION_SERVLET_ENABLED=true
export OTEL_INSTRUMENTATION_JDBC_ENABLED=true

Debug logging: Enable agent debug output to diagnose issues:

shell
export OTEL_JAVAAGENT_DEBUG=true

What is Uptrace?

Uptrace is an OpenTelemetry APM that supports distributed tracing, metrics, and logs. You can use it to monitor applications and troubleshoot issues.

Uptrace Overview

Uptrace comes with an intuitive query builder, rich dashboards, alerting rules with notifications, and integrations for most languages and frameworks.

Uptrace can process billions of spans and metrics on a single server and allows you to monitor your applications at 10x lower cost.

In just a few minutes, you can try Uptrace by visiting the cloud demo (no login required) or running it locally with Docker. The source code is available on GitHub.

What's next?

Your Tomcat server is now instrumented with OpenTelemetry for comprehensive monitoring. Next steps: