0
# Automatic Instrumentation
1
2
Comprehensive automatic instrumentation for web frameworks, databases, HTTP clients, message queues, AI/ML libraries, and 80+ other popular Python packages through sophisticated monkey-patching. This enables zero-code-change observability for most Python applications.
3
4
## Capabilities
5
6
### Manual Patching
7
8
Selective instrumentation of specific libraries and frameworks for precise control over which components are monitored.
9
10
```python { .api }
11
def patch(
12
# Web Frameworks
13
django: bool = None,
14
flask: bool = None,
15
fastapi: bool = None,
16
sanic: bool = None,
17
bottle: bool = None,
18
molten: bool = None,
19
pyramid: bool = None,
20
tornado: bool = None,
21
aiohttp: bool = None,
22
23
# Databases
24
psycopg: bool = None,
25
mysql: bool = None,
26
mysqldb: bool = None,
27
pymysql: bool = None,
28
sqlite3: bool = None,
29
pymongo: bool = None,
30
mongoengine: bool = None,
31
cassandra: bool = None,
32
33
# Caching
34
redis: bool = None,
35
rediscluster: bool = None,
36
aioredis: bool = None,
37
aredis: bool = None,
38
pymemcache: bool = None,
39
40
# HTTP Clients
41
requests: bool = None,
42
httpx: bool = None,
43
httplib: bool = None,
44
urllib3: bool = None,
45
46
# AWS Services
47
boto: bool = None,
48
botocore: bool = None,
49
aiobotocore: bool = None,
50
51
# Message Queues
52
celery: bool = None,
53
kombu: bool = None,
54
dramatiq: bool = None,
55
rq: bool = None,
56
57
# Search
58
elasticsearch: bool = None,
59
algoliasearch: bool = None,
60
61
# AI/ML Libraries
62
openai: bool = None,
63
anthropic: bool = None,
64
langchain: bool = None,
65
langgraph: bool = None,
66
google_genai: bool = None,
67
google_generativeai: bool = None,
68
litellm: bool = None,
69
70
# Testing
71
pytest: bool = None,
72
pytest_bdd: bool = None,
73
pytest_benchmark: bool = None,
74
75
# Async
76
asyncio: bool = None,
77
gevent: bool = None,
78
79
# Other
80
grpc: bool = None,
81
graphql: bool = None,
82
jinja2: bool = None,
83
mako: bool = None,
84
protobuf: bool = None,
85
avro: bool = None,
86
87
# Configuration
88
raise_errors: bool = True,
89
**kwargs
90
) -> None:
91
"""
92
Manually patch specific modules for automatic instrumentation.
93
94
Parameters:
95
- Library-specific boolean flags to enable/disable instrumentation
96
- raise_errors: Whether to raise exceptions if patching fails (default: True)
97
- **kwargs: Additional library flags not explicitly listed
98
99
Raises:
100
- ModuleNotFoundException: If a requested module doesn't have instrumentation
101
- ImportError: If a requested module isn't installed
102
"""
103
```
104
105
Usage examples:
106
107
```python
108
from ddtrace import patch
109
110
# Patch specific components for a web application
111
patch(
112
django=True, # Django web framework
113
psycopg=True, # PostgreSQL database
114
redis=True, # Redis caching
115
requests=True, # HTTP client
116
celery=True # Background tasks
117
)
118
119
# Patch AI/ML components for an AI application
120
patch(
121
fastapi=True, # API framework
122
openai=True, # OpenAI integration
123
langchain=True, # LangChain framework
124
pymongo=True # MongoDB database
125
)
126
127
# Minimal patching for microservice
128
patch(flask=True, requests=True)
129
130
# Error handling
131
try:
132
patch(nonexistent_library=True)
133
except ModuleNotFoundException as e:
134
print(f"Library not supported: {e}")
135
except ImportError as e:
136
print(f"Library not installed: {e}")
137
```
138
139
### Deprecated Bulk Patching
140
141
```python { .api }
142
def patch_all(**patch_modules: bool) -> None:
143
"""
144
Automatically patch all supported modules (deprecated).
145
146
Parameters:
147
- **patch_modules: Override flags for specific modules
148
149
Note: This function is deprecated in favor of patch() and DD_PATCH_MODULES
150
environment variable. It will be removed in a future version.
151
"""
152
```
153
154
### Environment-Based Configuration
155
156
Configure automatic instrumentation through environment variables for deployment flexibility.
157
158
```python
159
import os
160
161
# Enable instrumentation via environment variables
162
os.environ['DD_PATCH_MODULES'] = 'django:true,redis:true,psycopg:true'
163
164
# Or disable specific modules
165
os.environ['DD_PATCH_MODULES'] = 'django:true,redis:false,celery:true'
166
167
# Import ddtrace to apply environment-based patching
168
import ddtrace.auto # Automatically applies DD_PATCH_MODULES configuration
169
```
170
171
### Web Framework Integration
172
173
#### Django
174
175
Comprehensive Django integration covering ORM, middleware, templates, and admin interface.
176
177
```python
178
from ddtrace import patch
179
180
patch(django=True)
181
182
# Automatically instruments:
183
# - HTTP request/response handling
184
# - Database queries via Django ORM
185
# - Template rendering
186
# - Cache operations
187
# - Authentication and sessions
188
# - Admin interface interactions
189
# - Middleware processing
190
# - Static file serving
191
192
# Example Django view with automatic instrumentation
193
def user_profile(request, user_id):
194
# HTTP request is automatically traced
195
user = User.objects.get(id=user_id) # Database query traced
196
return render(request, 'profile.html', {'user': user}) # Template rendering traced
197
```
198
199
#### Flask
200
201
Flask application instrumentation including routes, templates, and extensions.
202
203
```python
204
from ddtrace import patch
205
from flask import Flask
206
207
patch(flask=True)
208
209
app = Flask(__name__)
210
211
# Automatically instruments:
212
# - Route handling and request processing
213
# - Template rendering (Jinja2)
214
# - Error handling
215
# - Before/after request hooks
216
# - Blueprint operations
217
# - Session management
218
219
@app.route('/api/users/<int:user_id>')
220
def get_user(user_id):
221
# Route automatically traced with URL pattern
222
user_data = fetch_user_from_db(user_id) # If DB is patched, this is traced too
223
return jsonify(user_data)
224
```
225
226
#### FastAPI
227
228
Modern async API framework instrumentation with automatic OpenAPI integration.
229
230
```python
231
from ddtrace import patch
232
from fastapi import FastAPI
233
234
patch(fastapi=True)
235
236
app = FastAPI()
237
238
# Automatically instruments:
239
# - Async request handling
240
# - Path parameters and query parameters
241
# - Request/response serialization
242
# - Dependency injection
243
# - Background tasks
244
# - WebSocket connections
245
# - OpenAPI documentation generation
246
247
@app.post("/items/")
248
async def create_item(item: ItemModel):
249
# Async endpoint automatically traced
250
result = await save_item_to_db(item) # Async DB operation traced
251
return result
252
```
253
254
### Database Integration
255
256
#### PostgreSQL (psycopg2/psycopg3)
257
258
```python
259
from ddtrace import patch
260
261
patch(psycopg=True)
262
263
# Automatically instruments:
264
# - SQL query execution
265
# - Connection pooling
266
# - Transaction management
267
# - Cursor operations
268
# - Prepared statements
269
270
import psycopg2
271
272
conn = psycopg2.connect("dbname=mydb user=myuser")
273
cursor = conn.cursor()
274
275
# This query is automatically traced with SQL statement and parameters
276
cursor.execute("SELECT * FROM users WHERE age > %s", (25,))
277
results = cursor.fetchall()
278
```
279
280
#### MongoDB
281
282
```python
283
from ddtrace import patch
284
285
patch(pymongo=True, mongoengine=True)
286
287
# PyMongo instrumentation
288
from pymongo import MongoClient
289
290
client = MongoClient('mongodb://localhost:27017/')
291
db = client.mydb
292
293
# Collection operations automatically traced
294
users = db.users.find({"age": {"$gt": 25}})
295
296
# MongoEngine instrumentation
297
from mongoengine import Document, StringField, IntField
298
299
class User(Document):
300
name = StringField(required=True)
301
age = IntField()
302
303
# ORM operations automatically traced
304
user = User.objects(age__gt=25).first()
305
```
306
307
#### Redis
308
309
```python
310
from ddtrace import patch
311
312
patch(redis=True, aioredis=True)
313
314
# Redis instrumentation
315
import redis
316
317
r = redis.Redis(host='localhost', port=6379, db=0)
318
319
# Cache operations automatically traced
320
r.set('user:123', 'john_doe')
321
username = r.get('user:123')
322
323
# Async Redis instrumentation
324
import aioredis
325
326
async def cache_operation():
327
redis_client = aioredis.from_url("redis://localhost")
328
await redis_client.set('async_key', 'value') # Traced
329
return await redis_client.get('async_key') # Traced
330
```
331
332
### HTTP Client Integration
333
334
#### Requests
335
336
```python
337
from ddtrace import patch
338
339
patch(requests=True)
340
341
import requests
342
343
# HTTP requests automatically traced with URL, method, status code
344
response = requests.get('https://api.example.com/users')
345
data = response.json()
346
347
# POST requests with request/response details
348
response = requests.post(
349
'https://api.example.com/users',
350
json={'name': 'John', 'email': 'john@example.com'}
351
)
352
```
353
354
#### HTTPX (Async HTTP)
355
356
```python
357
from ddtrace import patch
358
359
patch(httpx=True)
360
361
import httpx
362
363
# Sync client
364
with httpx.Client() as client:
365
response = client.get('https://api.example.com/data') # Traced
366
367
# Async client
368
async with httpx.AsyncClient() as client:
369
response = await client.get('https://api.example.com/data') # Traced
370
```
371
372
### AI/ML Library Integration
373
374
#### OpenAI
375
376
```python
377
from ddtrace import patch
378
379
patch(openai=True)
380
381
from openai import OpenAI
382
383
client = OpenAI()
384
385
# Chat completions automatically traced with token usage, model info
386
response = client.chat.completions.create(
387
model="gpt-3.5-turbo",
388
messages=[{"role": "user", "content": "Hello, world!"}]
389
)
390
391
# Embeddings and other operations also traced
392
embeddings = client.embeddings.create(
393
model="text-embedding-ada-002",
394
input="Text to embed"
395
)
396
```
397
398
#### LangChain
399
400
```python
401
from ddtrace import patch
402
403
patch(langchain=True)
404
405
# LangChain operations automatically traced
406
from langchain.llms import OpenAI
407
from langchain.chains import LLMChain
408
from langchain.prompts import PromptTemplate
409
410
llm = OpenAI()
411
prompt = PromptTemplate(template="Tell me about {topic}")
412
chain = LLMChain(llm=llm, prompt=prompt)
413
414
# Chain execution automatically traced with input/output
415
result = chain.run(topic="machine learning")
416
```
417
418
### Message Queue Integration
419
420
#### Celery
421
422
```python
423
from ddtrace import patch
424
425
patch(celery=True)
426
427
from celery import Celery
428
429
app = Celery('myapp', broker='redis://localhost:6379')
430
431
# Task definitions automatically instrumented
432
@app.task
433
def process_data(data_id):
434
# Task execution automatically traced
435
data = fetch_data(data_id)
436
return process_and_save(data)
437
438
# Task calls traced as both producer and consumer
439
result = process_data.delay('123')
440
```
441
442
### Testing Integration
443
444
#### pytest
445
446
```python
447
from ddtrace import patch
448
449
patch(pytest=True)
450
451
# Test execution automatically traced
452
# - Test discovery and collection
453
# - Individual test execution time
454
# - Test outcomes (pass/fail/skip)
455
# - Test parameters and fixtures
456
# - Coverage information (if available)
457
458
def test_user_creation():
459
# Test execution automatically traced
460
user = create_user("test@example.com")
461
assert user.email == "test@example.com"
462
463
@pytest.mark.parametrize("email", ["test1@example.com", "test2@example.com"])
464
def test_email_validation(email):
465
# Parameterized tests traced individually
466
assert validate_email(email)
467
```
468
469
### Advanced Configuration
470
471
#### Per-Integration Configuration
472
473
```python
474
from ddtrace import config, patch
475
476
# Configure before patching
477
config.django.service_name = "web-frontend"
478
config.redis.service_name = "cache-service"
479
config.psycopg.service_name = "database"
480
481
# Apply patches with custom configuration
482
patch(django=True, redis=True, psycopg=True)
483
```
484
485
#### Pin-based Configuration
486
487
```python
488
from ddtrace import Pin, patch
489
from ddtrace.contrib.redis import get_version
490
491
patch(redis=True)
492
493
import redis
494
495
# Customize Redis instrumentation
496
redis_client = redis.Redis()
497
pin = Pin.get_from(redis_client)
498
pin.clone(service="user-cache", tags={"cache.type": "user-data"}).onto(redis_client)
499
500
# Operations now use custom service name and tags
501
redis_client.set('user:123', 'data')
502
```
503
504
#### Global Tags and Service Mapping
505
506
```python
507
from ddtrace import config, patch
508
509
# Global configuration
510
config.service = "my-application"
511
config.env = "production"
512
config.version = "2.1.0"
513
514
# Service name mapping for integrations
515
config.service_mapping = {
516
'psycopg': 'postgres-primary',
517
'redis': 'redis-cache',
518
'requests': 'external-apis'
519
}
520
521
# Global tags applied to all spans
522
config.tags = {
523
'team': 'backend',
524
'region': 'us-east-1'
525
}
526
527
patch(psycopg=True, redis=True, requests=True)
528
```
529
530
### Error Handling and Debugging
531
532
```python
533
from ddtrace import patch
534
from ddtrace.contrib.integration_registry import ModuleNotFoundException
535
536
try:
537
patch(
538
django=True,
539
nonexistent_lib=True, # This will fail
540
raise_errors=True
541
)
542
except ModuleNotFoundException as e:
543
print(f"Integration not available: {e}")
544
# Continue with available integrations
545
patch(django=True, raise_errors=False)
546
547
# Check which integrations are available
548
from ddtrace.contrib import trace_integrations
549
550
available_integrations = trace_integrations()
551
print(f"Available integrations: {list(available_integrations.keys())}")
552
```
553
554
### Performance Considerations
555
556
```python
557
# Selective patching for performance-critical applications
558
patch(
559
# Essential components only
560
flask=True,
561
psycopg=True,
562
redis=True,
563
564
# Skip expensive instrumentations if not needed
565
jinja2=False,
566
graphql=False
567
)
568
569
# Configure sampling for high-throughput applications
570
from ddtrace import config
571
572
config.analytics_enabled = False # Disable analytics if not needed
573
config.priority_sampling = True # Use priority sampling
574
```
575
576
## Supported Libraries
577
578
ddtrace provides automatic instrumentation for 80+ Python libraries organized by category:
579
580
### Web Frameworks
581
- Django, Flask, FastAPI, Sanic, Bottle, Molten, Pyramid, Tornado, aiohttp
582
583
### Databases
584
- PostgreSQL (psycopg2/3), MySQL, MongoDB, Redis, Cassandra, Elasticsearch
585
586
### HTTP Clients
587
- requests, httpx, urllib3, aiohttp
588
589
### AWS Services
590
- boto3, botocore, aiobotocore
591
592
### Message Queues
593
- Celery, Kombu, Dramatiq, RQ
594
595
### AI/ML
596
- OpenAI, Anthropic, LangChain, LangGraph, Google AI, LiteLLM
597
598
### Testing
599
- pytest, pytest-bdd, pytest-benchmark
600
601
### And Many More
602
- gRPC, GraphQL, Jinja2, Mako, Protobuf, Avro, asyncio, gevent, and others
603
604
Each integration captures relevant metadata, timing information, and error states specific to that library's operations.