OpenTelemetry Pyramid: Instrumentation and Monitoring Guide
OpenTelemetry Pyramid instrumentation provides automatic tracing for HTTP requests, route handling, and template rendering in Pyramid web applications. With opentelemetry-instrumentation-pyramid, you can add observability to your Python web services and track request latencies, database queries, and errors across distributed systems.
Quick Reference
| Component | Package | Purpose |
|---|---|---|
| Pyramid Instrumentation | opentelemetry-instrumentation-pyramid | Auto-trace HTTP requests |
| SQLAlchemy Instrumentation | opentelemetry-instrumentation-sqlalchemy | Trace database queries |
| Requests Instrumentation | opentelemetry-instrumentation-requests | Trace outgoing HTTP calls |
| Auto-instrumentation | opentelemetry-bootstrap | Detect and install plugins |
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 quantitative measurements of application performance
- 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.
Prerequisites
- Python 3.8+
- Pyramid 1.7+
- pip package manager
Quick Start: For fastest setup without code changes, see the Python zero-code instrumentation guide.
Installation
Install the core packages for Pyramid instrumentation. For comprehensive Python instrumentation, see the OpenTelemetry Python guide.
# Core OpenTelemetry SDK
pip install opentelemetry-api opentelemetry-sdk
# Pyramid instrumentation
pip install opentelemetry-instrumentation-pyramid
# OTLP exporter
pip install opentelemetry-exporter-otlp
Optional packages depending on your stack:
# Database instrumentation
pip install opentelemetry-instrumentation-sqlalchemy
# HTTP client instrumentation
pip install opentelemetry-instrumentation-requests
pip install opentelemetry-instrumentation-urllib3
Basic Setup
Using Uptrace SDK
The simplest way to get started is with the Uptrace Python SDK, which bundles the OpenTelemetry SDK with sensible defaults:
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
import uptrace
# Configure OpenTelemetry with Uptrace
uptrace.configure_opentelemetry(
# Set dsn or UPTRACE_DSN env var.
# dsn="<FIXME>",
service_name="pyramid-app",
service_version="1.0.0",
)
# Instrument Pyramid before creating the app
PyramidInstrumentor().instrument()
def home(request):
return Response("Hello, World!")
def health(request):
return Response("OK")
if __name__ == "__main__":
with Configurator() as config:
config.add_route("home", "/")
config.add_view(home, route_name="home")
config.add_route("health", "/health")
config.add_view(health, route_name="health")
app = config.make_wsgi_app()
print("Listening on http://localhost:6543")
server = make_server("0.0.0.0", 6543, app)
server.serve_forever()
See the example on GitHub for more details.
Using OpenTelemetry SDK Directly
For a vendor-neutral setup, configure the OpenTelemetry SDK directly:
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource, SERVICE_NAME
from opentelemetry.instrumentation.pyramid import PyramidInstrumentor
# Configure resource attributes
resource = Resource.create({
SERVICE_NAME: "pyramid-app",
"service.version": "1.0.0",
})
# Set up tracing
provider = TracerProvider(resource=resource)
provider.add_span_processor(
BatchSpanProcessor(OTLPSpanExporter())
)
trace.set_tracer_provider(provider)
# Instrument Pyramid
PyramidInstrumentor().instrument()
def home(request):
return Response("Hello, World!")
if __name__ == "__main__":
with Configurator() as config:
config.add_route("home", "/")
config.add_view(home, route_name="home")
app = config.make_wsgi_app()
server = make_server("0.0.0.0", 6543, app)
server.serve_forever()
Auto-Instrumentation with Bootstrap
As an alternative to programmatic setup, you can use opentelemetry-instrument to run your application with automatic instrumentation:
# Install the distro package (includes opentelemetry-bootstrap CLI)
pip install opentelemetry-distro opentelemetry-instrumentation
# Detect and install instrumentation for installed libraries
opentelemetry-bootstrap -a install
# Run with auto-instrumentation
opentelemetry-instrument \
--service_name pyramid-app \
--traces_exporter otlp \
--metrics_exporter otlp \
--exporter_otlp_endpoint https://api.uptrace.dev:4317 \
--exporter_otlp_headers "uptrace-dsn=<FIXME>" \
python app.py
This approach requires no code changes at all. The agent detects Pyramid and other installed libraries automatically.
Custom Instrumentation
Add custom spans to trace specific business logic:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def create_order(request):
with tracer.start_as_current_span("create-order") as span:
order_data = request.json_body
span.set_attribute("order.customer_id", order_data.get("customer_id"))
span.set_attribute("order.item_count", len(order_data.get("items", [])))
try:
# Validate order
with tracer.start_as_current_span("validate-order"):
validate_order(order_data)
# Save to database
with tracer.start_as_current_span("save-order") as db_span:
db_span.set_attribute("db.operation", "INSERT")
db_span.set_attribute("db.table", "orders")
order_id = save_order(order_data)
span.set_attribute("order.id", order_id)
return Response(json={"order_id": order_id})
except Exception as e:
span.record_exception(e)
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
return Response(json={"error": str(e)}, status=500)
Database Instrumentation
Pyramid applications commonly use SQLAlchemy for database access. Add automatic tracing for all database queries:
pip install opentelemetry-instrumentation-sqlalchemy
from sqlalchemy import create_engine
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
engine = create_engine("postgresql://user:password@localhost/mydb")
# Instrument SQLAlchemy engine
SQLAlchemyInstrumentor().instrument(
engine=engine,
enable_commenter=True, # Add trace context to SQL comments
)
This captures all queries executed through the instrumented engine, including query text, execution time, and connection metadata.
For a detailed guide, see SQLAlchemy instrumentation.
Excluding URLs
Disable tracing on specific routes by setting an environment variable with URL patterns:
export OTEL_PYTHON_PYRAMID_EXCLUDED_URLS="client/.*/info,healthcheck,metrics"
This is useful for excluding health check endpoints and other high-frequency, low-value routes from tracing.
Capturing HTTP Headers
Request Headers
Capture incoming HTTP request headers as span attributes:
# Specific headers
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST="content-type,custom_request_header"
# Pattern matching
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST="Accept.*,X-.*"
# All headers
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST=".*"
Response Headers
Capture outgoing HTTP response headers:
# Specific headers
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE="content-type,custom_response_header"
# Pattern matching
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE="Content.*,X-.*"
Sanitizing Sensitive Headers
Prevent storing sensitive data from captured headers:
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS=".*session.*,set-cookie,authorization"
See documentation for details.
Environment Variables Configuration
Configure OpenTelemetry through environment variables for production deployments:
# Service identification
export OTEL_SERVICE_NAME="pyramid-app"
export OTEL_RESOURCE_ATTRIBUTES="service.version=1.0.0,deployment.environment=production"
# Exporter configuration
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.uptrace.dev:4317"
export OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<FIXME>"
export OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
# Sampling (optional - reduce volume in production)
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"
For the full list, see the OpenTelemetry environment variables reference.
Production Deployment
Using Gunicorn
Deploy with Gunicorn for production:
pip install gunicorn
gunicorn --bind 0.0.0.0:6543 --workers 4 "app:main()"
OpenTelemetry automatically instruments Gunicorn workers when PyramidInstrumentor is configured in your application.
Using Docker
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 6543
CMD ["gunicorn", "--bind", "0.0.0.0:6543", "--workers", "4", "app:main()"]
Run with environment variables:
docker run -p 6543:6543 \
-e OTEL_SERVICE_NAME=pyramid-app \
-e OTEL_EXPORTER_OTLP_ENDPOINT=https://api.uptrace.dev:4317 \
-e OTEL_EXPORTER_OTLP_HEADERS="uptrace-dsn=<FIXME>" \
pyramid-app
Troubleshooting
No traces appearing: Verify the OTLP endpoint is reachable and check that PyramidInstrumentor().instrument() is called before the WSGI app is created.
Missing spans for specific routes: Check if the route is excluded via OTEL_PYTHON_PYRAMID_EXCLUDED_URLS.
High memory usage: Reduce the batch processor queue size:
from opentelemetry.sdk.trace.export import BatchSpanProcessor
processor = BatchSpanProcessor(
exporter,
max_queue_size=512,
max_export_batch_size=128,
)
Debug logging: Enable verbose OpenTelemetry logging:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("opentelemetry").setLevel(logging.DEBUG)
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 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 Pyramid application is now instrumented with OpenTelemetry for comprehensive monitoring. Next steps:
- Flask instrumentation for an alternative Python web framework
- Django instrumentation for full-featured Python web applications
- SQLAlchemy instrumentation for database monitoring
- OpenTelemetry Python guide for deeper instrumentation options