Docling Pipelines supports OpenTelemetry (OTEL) for distributed tracing and observability. This guide covers installation, configuration, and usage of the telemetry features.
trace_id and span_id for direct navigation from logs to tracesOTEL_TRACES_SAMPLER_ARG# Install Docling Pipelines with telemetry support
uv pip install -e ".[telemetry]"
This installs the following packages:
opentelemetry-api - Core OTEL APIopentelemetry-sdk - OTEL SDK implementationopentelemetry-exporter-otlp-proto-grpc - OTLP gRPC exporteropentelemetry-instrumentation-fastapi - FastAPI auto-instrumentationDocling Pipelines works with any OTLP-compatible backend. Popular options:
Start Jaeger and Docling Pipelines API together:
# From project root
docker-compose -f docker/docker-compose.telemetry.yml up -d
# Verify services are running
docker-compose -f docker/docker-compose.telemetry.yml ps
Access services:
Test telemetry:
# Make a request
curl http://localhost:8000/api/v1/operators
# View traces in Jaeger UI
open http://localhost:16686
Stop services:
docker-compose -f docker/docker-compose.telemetry.yml down
If you want to run Jaeger separately:
docker run -d --name jaeger \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
jaegertracing/all-in-one:latest
Create or update your .env file:
# Enable telemetry
TELEMETRY_ENABLED=true
# Service identification
OTEL_SERVICE_NAME=docling-pipelines-dev
OTEL_SERVICE_VERSION=0.1.0
OTEL_DEPLOYMENT_ENVIRONMENT=development
# OTLP endpoint (Jaeger)
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
Run any flow normally - telemetry will be automatically enabled:
# CLI
docling-pipelines --flow-file sample_flows/quickstart/basic_ingest_extract.json
# API
docling-pipelines-api
Open Jaeger UI in your browser:
http://localhost:16686
Select “docling-pipelines-dev” from the service dropdown and click “Find Traces”.
| Variable | Description | Default |
|---|---|---|
TELEMETRY_ENABLED |
Master switch — enables both traces and metrics | false |
OTEL_SERVICE_NAME |
Service name in traces/metrics | docling-pipelines |
OTEL_EXPORTER_OTLP_ENDPOINT |
OTLP endpoint URL | http://localhost:4317 |
OTEL_SERVICE_VERSION |
Service version | 0.1.0 |
OTEL_DEPLOYMENT_ENVIRONMENT |
Environment name | development |
OTEL_EXPORTER_OTLP_HEADERS |
Authentication headers (e.g. Authorization=Basic ...) |
(none) |
OTEL_TRACES_SAMPLER_ARG |
Head-based sampling rate, 0.0–1.0 (1.0 = 100%) | 1.0 |
OTEL_METRIC_EXPORT_INTERVAL |
Metrics flush interval in milliseconds | 60000 |
Telemetry is configured once at deployment level, not per-flow:
Docker Compose:
services:
docling-pipelines:
environment:
- TELEMETRY_ENABLED=true
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
Kubernetes:
env:
- name: TELEMETRY_ENABLED
value: "true"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://otel-collector:4317"
All API requests are automatically traced and measured:
Spans — attributes captured:
http.method, http.url, http.scheme, http.targethttp.status_code, transaction.id, errorMetrics — instruments:
http.server.request.count — counter, labelled by method / route / status codehttp.server.request.duration — histogram in millisecondsAll operator executions are automatically traced and measured:
Spans — attributes captured:
operator.name, operator.short_name, operator.categoryjob.id, job_run.idoperator.processed_docs, operator.failed_docs, operator.total_docsMetrics — instruments:
operator.execution.count — counter, labelled by operator name / category / successoperator.execution.duration — histogram in millisecondsoperator.error.count — counter, labelled by operator name / categoryWhen JSON logging is enabled (DS_LOG_JSON=True) and telemetry is active, every log record includes:
{
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7"
}
Use these fields in Grafana to jump directly from a log line to its trace.
Flow Execution
├── HTTP POST /api/v1/flows/execute
│ ├── operator.IngestSourceOperator
│ │ └── processed_docs: 10
│ ├── operator.ExtractOperator
│ │ └── processed_docs: 10
│ └── operator.EmbeddingsOperator
│ └── processed_docs: 10
For production, route traces through an OTEL Collector:
# docker-compose.yml
services:
otel-collector:
image: otel/opentelemetry-collector:latest
ports:
- "4317:4317" # OTLP gRPC
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
command: ["--config=/etc/otel-collector-config.yaml"]
docling-pipelines:
environment:
- TELEMETRY_ENABLED=true
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
Docling Pipelines supports head-based sampling natively — no collector required:
# Sample 10% of traces (reduces both trace volume and exporter overhead)
OTEL_TRACES_SAMPLER_ARG=0.1
For tail-based sampling or more advanced strategies, route through an OTEL Collector:
# otel-collector-config.yaml
processors:
probabilistic_sampler:
sampling_percentage: 10
For production deployments:
# Local
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
# Production
OTEL_EXPORTER_OTLP_ENDPOINT=https://jaeger.example.com:4317
Grafana Cloud provides managed observability with Tempo for distributed tracing.
https://otlp-gateway-{region}.grafana.net/otlp123456)glc_)Grafana Cloud requires Basic authentication:
# Format: instance_id:api_token
echo -n "123456:glc_your_api_token_here" | base64
# Output: MTIzNDU2OmdsY195b3VyX2FwaV90b2tlbl9oZXJl
# Enable telemetry
TELEMETRY_ENABLED=true
# Service identification
OTEL_SERVICE_NAME=docling-pipelines-prod
OTEL_DEPLOYMENT_ENVIRONMENT=production
# Grafana Cloud endpoint (replace region: prod-us-east-0, prod-eu-west-0, etc.)
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway-prod-us-east-0.grafana.net/otlp
# Authentication (use your base64-encoded credentials)
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic {base64_encoded_credentials}
services:
docling-pipelines:
environment:
- TELEMETRY_ENABLED=true
- OTEL_SERVICE_NAME=docling-pipelines-prod
- OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway-prod-us-east-0.grafana.net/otlp
- OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic MTIzNDU2OmdsY195b3VyX2FwaV90b2tlbl9oZXJl
apiVersion: v1
kind: Secret
metadata:
name: grafana-cloud-creds
type: Opaque
stringData:
auth-header: "Authorization=Basic MTIzNDU2OmdsY195b3VyX2FwaV90b2tlbl9oZXJl"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: docling-pipelines
spec:
template:
spec:
containers:
- name: app
env:
- name: TELEMETRY_ENABLED
value: "true"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "https://otlp-gateway-prod-us-east-0.grafana.net/otlp"
- name: OTEL_EXPORTER_OTLP_HEADERS
valueFrom:
secretKeyRef:
name: grafana-cloud-creds
key: auth-header
{ service.name="docling-pipelines-prod" }
OTEL_EXPORTER_OTLP_ENDPOINT=https://tempo.example.com:4317
# Via OTEL Collector with Datadog exporter
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
# Via OTEL Collector with X-Ray exporter
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
echo $TELEMETRY_ENABLED
# Should output: true
curl http://localhost:4317
# Look for: "Telemetry initialized successfully"
docling-pipelines --flow-file flow.json 2>&1 | grep -i telemetry
TELEMETRY_ENABLED=false
OTEL_TRACES_SAMPLER_ARG=0.1 # sample 10%
OTEL_METRIC_EXPORT_INTERVAL=120000 # flush every 2 minutes
If you see warnings about missing OpenTelemetry packages:
# Reinstall with telemetry dependencies
uv pip install -e ".[telemetry]"
from docpipe.utils.infrastructure import get_telemetry_service
telemetry = get_telemetry_service()
print(f"Telemetry enabled: {telemetry.is_enabled}")
print(f"Metrics enabled: {telemetry.metrics_enabled}")
# Run a simple flow
docling-pipelines --flow-file sample_flows/quickstart/complete_pipeline_ollama.json
# Check Jaeger UI for traces
open http://localhost:16686
In Jaeger UI, click on a trace and verify:
http.method, http.url, http.status_codeoperator.name, operator.categoryIn Grafana, query the Prometheus/OTLP data source:
http_server_request_count_total
operator_execution_count_total
operator_error_count_total
OTEL_SERVICE_NAME to identify your instanceOTEL_DEPLOYMENT_ENVIRONMENT to distinguish dev/staging/prodOTEL_TRACES_SAMPLER_ARG=0.1 for 10% samplingDS_LOG_JSON=True to get trace_id/span_id in log recordsoperator.error.count to alert on operator failuresFor issues or questions: