0
# Performance Monitoring
1
2
Distributed tracing with transactions and spans for monitoring application performance, database queries, external service calls, and custom operations with automatic and manual instrumentation support.
3
4
## Capabilities
5
6
### Transaction Management
7
8
Create and manage top-level transactions representing complete operations like HTTP requests, background jobs, or business processes.
9
10
```python { .api }
11
def start_transaction(
12
transaction: Optional[Union[Transaction, Dict[str, Any]]] = None,
13
instrumenter: str = INSTRUMENTER.SENTRY,
14
custom_sampling_context: Optional[Dict[str, Any]] = None,
15
**kwargs
16
) -> Union[Transaction, NoOpSpan]:
17
"""
18
Start a new transaction for performance monitoring.
19
20
Parameters:
21
- transaction: Transaction name or transaction object
22
- instrumenter: Instrumentation source identifier
23
- custom_sampling_context: Additional context for sampling decisions
24
- **kwargs: Additional transaction properties (op, description, source, etc.)
25
26
Returns:
27
Transaction or NoOpSpan: Active transaction or no-op if disabled/sampled out
28
"""
29
```
30
31
**Usage Examples:**
32
33
```python
34
import sentry_sdk
35
36
# Simple transaction
37
with sentry_sdk.start_transaction(name="process_order", op="function") as transaction:
38
# Process order logic
39
validate_order()
40
charge_payment()
41
fulfill_order()
42
43
# Transaction with custom properties
44
transaction = sentry_sdk.start_transaction(
45
name="data_pipeline",
46
op="task",
47
description="Process daily analytics batch",
48
source="custom",
49
data={"batch_size": 1000, "source": "analytics_db"}
50
)
51
try:
52
process_analytics_batch()
53
finally:
54
transaction.finish()
55
56
# HTTP request transaction (typically handled by web framework integrations)
57
def handle_api_request(request):
58
with sentry_sdk.start_transaction(
59
name=f"{request.method} {request.path}",
60
op="http.server",
61
source="route"
62
) as transaction:
63
transaction.set_tag("http.method", request.method)
64
transaction.set_tag("endpoint", request.path)
65
return process_request(request)
66
```
67
68
### Span Creation
69
70
Create child spans within transactions to measure specific operations like database queries, API calls, or computational tasks.
71
72
```python { .api }
73
def start_span(
74
instrumenter: str = INSTRUMENTER.SENTRY,
75
**kwargs
76
) -> Span:
77
"""
78
Start a new span within the current transaction.
79
80
Parameters:
81
- instrumenter: Instrumentation source identifier
82
- **kwargs: Span properties (op, description, tags, data, etc.)
83
84
Returns:
85
Span: Active span for the operation
86
"""
87
```
88
89
**Usage Examples:**
90
91
```python
92
import sentry_sdk
93
94
def process_user_data(user_id):
95
with sentry_sdk.start_transaction(name="process_user_data", op="function"):
96
# Database query span
97
with sentry_sdk.start_span(op="db.query", description="fetch user") as span:
98
span.set_tag("db.table", "users")
99
span.set_data("user_id", user_id)
100
user = database.get_user(user_id)
101
102
# API call span
103
with sentry_sdk.start_span(
104
op="http.client",
105
description="POST /api/enrichment"
106
) as span:
107
span.set_tag("http.method", "POST")
108
span.set_data("url", "https://api.example.com/enrichment")
109
enriched_data = api_client.enrich_user_data(user)
110
111
# Processing span
112
with sentry_sdk.start_span(op="function", description="transform_data"):
113
result = transform_user_data(enriched_data)
114
115
return result
116
```
117
118
### Active Span Access
119
120
Get the currently active span for adding metadata, measurements, or creating child spans.
121
122
```python { .api }
123
def get_current_span(scope: Optional[Scope] = None) -> Optional[Span]:
124
"""
125
Get the currently active span.
126
127
Parameters:
128
- scope: Scope to check for active span (uses current scope if None)
129
130
Returns:
131
Optional[Span]: Current span if active, None otherwise
132
"""
133
```
134
135
**Usage Examples:**
136
137
```python
138
import sentry_sdk
139
140
def database_operation(query):
141
span = sentry_sdk.get_current_span()
142
if span:
143
span.set_tag("db.system", "postgresql")
144
span.set_data("db.statement", query)
145
span.set_data("db.operation", "select")
146
147
return execute_query(query)
148
149
def add_custom_measurements():
150
span = sentry_sdk.get_current_span()
151
if span:
152
span.set_measurement("memory_usage_mb", get_memory_usage(), "megabyte")
153
span.set_measurement("cpu_usage_percent", get_cpu_usage(), "percent")
154
span.set_data("custom_metric", calculate_business_metric())
155
```
156
157
### Distributed Tracing
158
159
Connect traces across service boundaries using W3C Trace Context headers for distributed system monitoring.
160
161
```python { .api }
162
def continue_trace(
163
environ_or_headers: Union[Dict[str, str], Dict[str, Any]],
164
op: Optional[str] = None,
165
name: Optional[str] = None,
166
source: Optional[str] = None,
167
origin: str = "manual"
168
) -> Transaction:
169
"""
170
Continue a distributed trace from incoming headers.
171
172
Parameters:
173
- environ_or_headers: WSGI environ dict or HTTP headers dict
174
- op: Transaction operation type
175
- name: Transaction name
176
- source: Transaction source identifier
177
- origin: Trace origin identifier
178
179
Returns:
180
Transaction: Connected transaction continuing the distributed trace
181
"""
182
183
def get_traceparent() -> Optional[str]:
184
"""
185
Get W3C traceparent header value for outgoing requests.
186
187
Returns:
188
Optional[str]: Traceparent header value or None if no active transaction
189
"""
190
191
def get_baggage() -> Optional[str]:
192
"""
193
Get W3C baggage header value for outgoing requests.
194
195
Returns:
196
Optional[str]: Baggage header value or None if no baggage data
197
"""
198
```
199
200
**Usage Examples:**
201
202
```python
203
import sentry_sdk
204
import requests
205
206
# Server: Continue trace from incoming request
207
def handle_incoming_request(request):
208
# Extract trace context from headers
209
transaction = sentry_sdk.continue_trace(
210
request.headers,
211
op="http.server",
212
name=f"{request.method} {request.path}",
213
source="route"
214
)
215
216
with transaction:
217
return process_request(request)
218
219
# Client: Propagate trace to outgoing request
220
def make_api_call(url, data):
221
headers = {}
222
223
# Add trace headers for distributed tracing
224
if traceparent := sentry_sdk.get_traceparent():
225
headers["traceparent"] = traceparent
226
227
if baggage := sentry_sdk.get_baggage():
228
headers["baggage"] = baggage
229
230
with sentry_sdk.start_span(op="http.client", description=f"POST {url}"):
231
response = requests.post(url, json=data, headers=headers)
232
return response.json()
233
```
234
235
### Automatic Tracing Decorator
236
237
Automatically create spans for function calls using the trace decorator.
238
239
```python { .api }
240
def trace(func: Callable) -> Callable:
241
"""
242
Decorator to automatically create spans for function calls.
243
244
The span will use the function name as description and 'function' as operation.
245
Additional span data can be set within the decorated function.
246
247
Parameters:
248
- func: Function to wrap with automatic tracing
249
250
Returns:
251
Callable: Decorated function that creates spans automatically
252
"""
253
```
254
255
**Usage Examples:**
256
257
```python
258
import sentry_sdk
259
260
@sentry_sdk.trace
261
def process_payment(amount, currency):
262
"""This function will automatically create a span."""
263
# Add custom span data
264
span = sentry_sdk.get_current_span()
265
if span:
266
span.set_tag("payment.currency", currency)
267
span.set_data("payment.amount", amount)
268
269
return payment_processor.charge(amount, currency)
270
271
@sentry_sdk.trace
272
def calculate_analytics(dataset):
273
"""Complex calculation with automatic timing."""
274
span = sentry_sdk.get_current_span()
275
if span:
276
span.set_data("dataset_size", len(dataset))
277
span.set_tag("operation", "analytics")
278
279
result = perform_complex_calculation(dataset)
280
281
if span:
282
span.set_data("result_count", len(result))
283
284
return result
285
286
# Usage in transaction context
287
def process_order(order_id):
288
with sentry_sdk.start_transaction(name="process_order", op="function"):
289
payment_result = process_payment(100.0, "USD") # Automatically traced
290
analytics = calculate_analytics(order_data) # Automatically traced
291
return finalize_order(order_id, payment_result)
292
```
293
294
### Span Modification
295
296
Update properties of the currently active span without needing a direct reference to the span object.
297
298
```python { .api }
299
def update_current_span(
300
op: Optional[str] = None,
301
name: Optional[str] = None,
302
attributes: Optional[Dict[str, Union[str, int, float, bool]]] = None,
303
data: Optional[Dict[str, Any]] = None # Deprecated
304
) -> None:
305
"""
306
Update the current active span with the provided parameters.
307
308
Parameters:
309
- op: The operation name for the span (e.g., "http.client", "db.query")
310
- name: The human-readable name/description for the span
311
- attributes: Key-value pairs to add as attributes to the span
312
- data: Deprecated, use attributes instead
313
"""
314
```
315
316
**Usage Examples:**
317
318
```python
319
import sentry_sdk
320
from sentry_sdk.consts import OP
321
322
# Start a span and update it later
323
with sentry_sdk.start_span(op="function", name="process_data") as span:
324
user_id = get_user_id()
325
326
# Update span with additional context as we learn more
327
sentry_sdk.update_current_span(
328
name=f"process_data_for_user_{user_id}",
329
attributes={
330
"user_id": user_id,
331
"batch_size": 50,
332
"processing_type": "standard"
333
}
334
)
335
336
# Process data...
337
result = expensive_operation()
338
339
# Update with results
340
sentry_sdk.update_current_span(
341
attributes={
342
"result_count": len(result),
343
"success": True
344
}
345
)
346
```
347
348
## Span Interface
349
350
### Span Properties and Methods
351
352
```python { .api }
353
class Span:
354
def set_tag(self, key: str, value: str) -> None:
355
"""Set a tag on the span."""
356
357
def set_data(self, key: str, value: Any) -> None:
358
"""Set structured data on the span."""
359
360
def set_measurement(self, name: str, value: float, unit: str = "") -> None:
361
"""Set a performance measurement."""
362
363
def set_status(self, status: str) -> None:
364
"""Set span status ('ok', 'cancelled', 'internal_error', etc.)."""
365
366
def set_http_status(self, http_status: int) -> None:
367
"""Set HTTP status code and derive span status."""
368
369
def finish(self, end_timestamp: Optional[datetime] = None) -> None:
370
"""Finish the span with optional custom end time."""
371
372
def to_json(self) -> Dict[str, Any]:
373
"""Serialize span to JSON representation."""
374
375
@property
376
def span_id(self) -> str:
377
"""Unique span identifier."""
378
379
@property
380
def trace_id(self) -> str:
381
"""Trace identifier shared across distributed trace."""
382
383
@property
384
def parent_span_id(self) -> Optional[str]:
385
"""Parent span identifier."""
386
387
@property
388
def sampled(self) -> Optional[bool]:
389
"""Whether this span is sampled for tracing."""
390
```
391
392
### Transaction-Specific Interface
393
394
```python { .api }
395
class Transaction(Span):
396
def set_name(self, name: str, source: Optional[str] = None) -> None:
397
"""Set transaction name and source."""
398
399
@property
400
def name(self) -> str:
401
"""Transaction name."""
402
403
@property
404
def source(self) -> str:
405
"""Transaction source ('custom', 'route', 'url', etc.)."""
406
```
407
408
## Performance Data
409
410
### Automatic Measurements
411
412
The SDK automatically collects:
413
- **Span duration**: Start and end timestamps
414
- **HTTP metrics**: Status codes, response sizes, request/response times
415
- **Database metrics**: Query timing, connection info, affected rows
416
- **Cache metrics**: Hit/miss ratios, operation timing
417
- **Queue metrics**: Job processing time, queue depth
418
419
### Custom Measurements
420
421
Add custom performance measurements:
422
423
```python
424
span = sentry_sdk.get_current_span()
425
if span:
426
# Time-based measurements
427
span.set_measurement("processing_time", 142.5, "millisecond")
428
span.set_measurement("wait_time", 2.3, "second")
429
430
# Size measurements
431
span.set_measurement("payload_size", 1024, "byte")
432
span.set_measurement("result_count", 50, "none")
433
434
# Rate measurements
435
span.set_measurement("throughput", 1500, "per_second")
436
span.set_measurement("error_rate", 0.02, "ratio")
437
```
438
439
## Integration with Scopes
440
441
Performance monitoring integrates with scope management:
442
- Transactions and spans inherit scope context (tags, user, extra data)
443
- Performance events include breadcrumbs and contextual information
444
- Scope modifications during spans affect the span's metadata
445
- Automatic correlation between errors and performance data