docs(python): Update stream mode in tracing files (tracing part 3/3)#18533
docs(python): Update stream mode in tracing files (tracing part 3/3)#18533inventarSarah wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
a1d549e to
9da9987
Compare
| ) as span: | ||
| try: | ||
| # Check inventory availability | ||
| inventory_start = time.time() |
There was a problem hiding this comment.
Bug: Code examples in the span-metrics documentation use functions from the time, psutil, and os modules without importing them, which will cause a NameError at runtime.
Severity: HIGH
Suggested Fix
Add import time to the E-Commerce examples. Add import psutil and import os to the Data Processing Pipeline examples to make the code snippets self-contained and runnable.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: docs/platforms/python/tracing/span-metrics/examples.mdx#L675
Potential issue: In the E-Commerce "Order processing service" examples for both
Transaction and Stream modes, the code uses `time.time()` to measure execution time but
fails to import the `time` module. Similarly, the Data Processing Pipeline examples use
`psutil.cpu_percent()`, `psutil.Process().memory_info()`, and `os.path.getsize()`
without importing the `psutil` or `os` modules. Users copying these examples will
encounter `NameError` exceptions at runtime when these functions are called.
Also affects:
docs/platforms/python/tracing/span-metrics/examples.mdx:614docs/platforms/python/tracing/span-metrics/examples.mdx:801docs/platforms/python/tracing/span-metrics/examples.mdx:809docs/platforms/python/tracing/span-metrics/examples.mdx:887docs/platforms/python/tracing/span-metrics/examples.mdx:895
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
added the missing imports
| <Alert> | ||
| In **transaction mode**, `sentry_sdk.continue_trace()` returns a transaction, but does not start it. To start the transaction, use `start_transaction()`. | ||
|
|
||
| In **stream mode**, `sentry_sdk.traces.continue_trace()` replaces `sentry_sdk.continue_trace()` and is not a context manager. Instead, it sets the propagation context, and the next span created with `sentry_sdk.traces.start_span()` picks it up automatically. |
There was a problem hiding this comment.
Instead is confusing here, both old and new set the propagation context.
| In **stream mode**, `sentry_sdk.traces.continue_trace()` replaces `sentry_sdk.continue_trace()` and is not a context manager. Instead, it sets the propagation context, and the next span created with `sentry_sdk.traces.start_span()` picks it up automatically. | |
| In **stream mode**, `sentry_sdk.traces.continue_trace()` replaces `sentry_sdk.continue_trace()` and is not a context manager. The next span created with `sentry_sdk.traces.start_span()` picks it up automatically. |
sentrivana
left a comment
There was a problem hiding this comment.
Approving to not block, but please see comments 🙏🏻
| "parent_sample_rate": Optional[float], # the sample rate used by the parent (SDK-provided) | ||
| "attributes": dict[str, Any] # attributes set at span-creation time (SDK- and user-provided) | ||
| }, | ||
| "custom_sampling_context": Optional[dict[str, Any]] # additional custom data for sampling |
There was a problem hiding this comment.
The SDK will put whatever the user sets as custom sampling context on the top level, next to span_context, so there is no custom_sampling_context key (unless the user explicitly set it)
| "custom_sampling_context": Optional[dict[str, Any]] # additional custom data for sampling | |
| ... # additional custom key-value pairs for sampling set via custom sampling context |
| custom_sampling_ctx = sampling_context.get("custom_sampling_context") or {} | ||
| environment = os.environ.get("ENVIRONMENT", "development") | ||
|
|
||
| # Sample all spans in development | ||
| if environment == "development": | ||
| return 1.0 | ||
|
|
||
| # Sample more spans if there are recent errors | ||
| # Note: hasRecentErrors is a custom attribute that needs to be set | ||
| if custom_sampling_ctx.get("hasRecentErrors") is True: | ||
| return 0.8 |
There was a problem hiding this comment.
There won't be a custom_sampling_context key in stream mode -- the user-set hasRecentErrors will be a top-level key of sampling_context
| custom_sampling_ctx = sampling_context.get("custom_sampling_context") or {} | |
| environment = os.environ.get("ENVIRONMENT", "development") | |
| # Sample all spans in development | |
| if environment == "development": | |
| return 1.0 | |
| # Sample more spans if there are recent errors | |
| # Note: hasRecentErrors is a custom attribute that needs to be set | |
| if custom_sampling_ctx.get("hasRecentErrors") is True: | |
| return 0.8 | |
| environment = os.environ.get("ENVIRONMENT", "development") | |
| # Sample all spans in development | |
| if environment == "development": | |
| return 1.0 | |
| # Sample more spans if there are recent errors | |
| # Note: hasRecentErrors is a custom attribute that needs to be set | |
| if sampling_context.get("hasRecentErrors") is True: | |
| return 0.8 |
| custom_sampling_ctx = sampling_context.get("custom_sampling_context") or {} | ||
|
|
||
| # Always sample for premium users | ||
| # Note: user.tier is a custom attribute that needs to be set | ||
| if custom_sampling_ctx.get("user", {}).get("tier") == "premium": | ||
| return 1.0 | ||
|
|
||
| # Sample more spans for users experiencing errors | ||
| # Note: hasRecentErrors is a custom attribute | ||
| if custom_sampling_ctx.get("hasRecentErrors") is True: | ||
| return 0.8 |
There was a problem hiding this comment.
| custom_sampling_ctx = sampling_context.get("custom_sampling_context") or {} | |
| # Always sample for premium users | |
| # Note: user.tier is a custom attribute that needs to be set | |
| if custom_sampling_ctx.get("user", {}).get("tier") == "premium": | |
| return 1.0 | |
| # Sample more spans for users experiencing errors | |
| # Note: hasRecentErrors is a custom attribute | |
| if custom_sampling_ctx.get("hasRecentErrors") is True: | |
| return 0.8 | |
| # Always sample for premium users | |
| # Note: user.tier is a custom attribute that needs to be set | |
| if sampling_context.get("user", {}).get("tier") == "premium": | |
| return 1.0 | |
| # Sample more spans for users experiencing errors | |
| # Note: hasRecentErrors is a custom attribute | |
| if sampling_context.get("hasRecentErrors") is True: | |
| return 0.8 |
| custom_sampling_context = sampling_context.get("custom_sampling_context") or {} | ||
|
|
||
| # Sample based on user segment | ||
| # Note: user.segment is a custom attribute | ||
| user_segment = custom_sampling_context.get("user", {}).get("segment") | ||
| if user_segment == "enterprise": | ||
| return 0.8 | ||
| elif user_segment == "premium": | ||
| return 0.5 | ||
|
|
||
| # Sample based on transaction value | ||
| # Note: transaction.value is a custom attribute | ||
| transaction_value = custom_sampling_context.get("transaction", {}).get("value") | ||
| if transaction_value is not None and transaction_value > 1000: # High-value transactions | ||
| return 0.7 | ||
|
|
||
| # Sample based on error rate in the service | ||
| # Note: service.error_rate is a custom attribute | ||
| error_rate = custom_sampling_context.get("service", {}).get("error_rate") |
There was a problem hiding this comment.
| custom_sampling_context = sampling_context.get("custom_sampling_context") or {} | |
| # Sample based on user segment | |
| # Note: user.segment is a custom attribute | |
| user_segment = custom_sampling_context.get("user", {}).get("segment") | |
| if user_segment == "enterprise": | |
| return 0.8 | |
| elif user_segment == "premium": | |
| return 0.5 | |
| # Sample based on transaction value | |
| # Note: transaction.value is a custom attribute | |
| transaction_value = custom_sampling_context.get("transaction", {}).get("value") | |
| if transaction_value is not None and transaction_value > 1000: # High-value transactions | |
| return 0.7 | |
| # Sample based on error rate in the service | |
| # Note: service.error_rate is a custom attribute | |
| error_rate = custom_sampling_context.get("service", {}).get("error_rate") | |
| # Sample based on user segment | |
| # Note: user.segment is a custom attribute | |
| user_segment = sampling_context.get("user", {}).get("segment") | |
| if user_segment == "enterprise": | |
| return 0.8 | |
| elif user_segment == "premium": | |
| return 0.5 | |
| # Sample based on transaction value | |
| # Note: transaction.value is a custom attribute | |
| transaction_value = sampling_context.get("transaction", {}).get("value") | |
| if transaction_value is not None and transaction_value > 1000: # High-value transactions | |
| return 0.7 | |
| # Sample based on error rate in the service | |
| # Note: service.error_rate is a custom attribute | |
| error_rate = sampling_context.get("service", {}).get("error_rate") |
| custom_sampling_ctx = sampling_context.get("custom_sampling_context") or {} | ||
|
|
||
| # Sample more spans with high memory usage | ||
| # Note: memory_usage_mb is a custom attribute | ||
| memory_usage = custom_sampling_ctx.get("memory_usage_mb") | ||
| if memory_usage is not None and memory_usage > 500: | ||
| return 0.8 | ||
|
|
||
| # Sample more spans with high CPU usage | ||
| # Note: cpu_percent is a custom attribute | ||
| cpu_percent = custom_sampling_ctx.get("cpu_percent") | ||
| if cpu_percent is not None and cpu_percent > 80: | ||
| return 0.8 | ||
|
|
||
| # Sample more spans with high database load | ||
| # Note: db_connections is a custom attribute | ||
| db_connections = custom_sampling_ctx.get("db_connections") |
There was a problem hiding this comment.
| custom_sampling_ctx = sampling_context.get("custom_sampling_context") or {} | |
| # Sample more spans with high memory usage | |
| # Note: memory_usage_mb is a custom attribute | |
| memory_usage = custom_sampling_ctx.get("memory_usage_mb") | |
| if memory_usage is not None and memory_usage > 500: | |
| return 0.8 | |
| # Sample more spans with high CPU usage | |
| # Note: cpu_percent is a custom attribute | |
| cpu_percent = custom_sampling_ctx.get("cpu_percent") | |
| if cpu_percent is not None and cpu_percent > 80: | |
| return 0.8 | |
| # Sample more spans with high database load | |
| # Note: db_connections is a custom attribute | |
| db_connections = custom_sampling_ctx.get("db_connections") | |
| # Sample more spans with high memory usage | |
| # Note: memory_usage_mb is a custom attribute | |
| memory_usage = sampling_context.get("memory_usage_mb") | |
| if memory_usage is not None and memory_usage > 500: | |
| return 0.8 | |
| # Sample more spans with high CPU usage | |
| # Note: cpu_percent is a custom attribute | |
| cpu_percent = sampling_context.get("cpu_percent") | |
| if cpu_percent is not None and cpu_percent > 80: | |
| return 0.8 | |
| # Sample more spans with high database load | |
| # Note: db_connections is a custom attribute | |
| db_connections = sampling_context.get("db_connections") |
| This guide provides practical examples of using span attributes and metrics to solve common monitoring and debugging challenges in Python applications. Each example demonstrates how to instrument different components, showing how they work together within a distributed trace to provide end-to-end visibility. | ||
|
|
||
| <Alert> | ||
| This page covers both transaction mode (default) and stream mode. See{" "} |
There was a problem hiding this comment.
| This page covers both transaction mode (default) and stream mode. See{" "} | |
| This page covers both transaction mode (default) and stream mode. See |
| span.set_attribute("storage.actual_upload_time_ms", | ||
| (time.time() - upload_start) * 1000) |
There was a problem hiding this comment.
| span.set_attribute("storage.actual_upload_time_ms", | |
| (time.time() - upload_start) * 1000) | |
| span.set_attribute( | |
| "storage.actual_upload_time_ms", | |
| (time.time() - upload_start) * 1000 | |
| ) |
| span.set_attribute("resource.memory_used_mb", | ||
| psutil.Process().memory_info().rss / (1024 * 1024)) |
There was a problem hiding this comment.
| span.set_attribute("resource.memory_used_mb", | |
| psutil.Process().memory_info().rss / (1024 * 1024)) | |
| span.set_attribute( | |
| "resource.memory_used_mb", | |
| psutil.Process().memory_info().rss / (1024 * 1024) | |
| ) |
DESCRIBE YOUR PR
This PR updates pages under Tracing with information about the new stream mode and the new Span APIs.
Part 3 out of 3
(result of splitting up PR #18511 into smaller parts)
Important
Broken links: I added links to the New Spans guide on these pages, but since this guide does not exist in this branch, we get a linting error.
Should only be merged after #18456
IS YOUR CHANGE URGENT?
Help us prioritize incoming PRs by letting us know when the change needs to go live.
SLA
Thanks in advance for your help!
PRE-MERGE CHECKLIST
Make sure you've checked the following before merging your changes:
LEGAL BOILERPLATE
Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.
EXTRA RESOURCES