Skip to content

Commit 14b9138

Browse files
authored
[python] document new rust_tracing integration (#11842)
A new Python SDK integration was created in getsentry/sentry-python#3717 + getsentry/sentry-python#3780 and this PR documents it.
1 parent 364c3a0 commit 14b9138

File tree

3 files changed

+189
-0
lines changed

3 files changed

+189
-0
lines changed

docs/platforms/python/integrations/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ The Sentry SDK uses integrations to hook into the functionality of popular libra
116116
| <LinkWithPlatformIcon platform="python.asyncio" label="asyncio" url="/platforms/python/integrations/asyncio" /> | |
117117
| <LinkWithPlatformIcon platform="python.pure_eval" label="Enhanced Locals" url="/platforms/python/integrations/pure_eval" /> | |
118118
| <LinkWithPlatformIcon platform="python.gnu_backtrace" label="GNU Backtrace" url="/platforms/python/integrations/gnu_backtrace" /> | |
119+
| <LinkWithPlatformIcon platform="python.rust_tracing" label="Rust Tracing" url="/platforms/python/integrations/rust_tracing" /> | |
119120
| <LinkWithPlatformIcon platform="python.socket" label="Socket" url="/platforms/python/integrations/socket" /> | |
120121
| <LinkWithPlatformIcon platform="python.sys_exit" label="sys.exit" url="/platforms/python/integrations/sys_exit" /> | |
121122
| <LinkWithPlatformIcon platform="python.tryton" label="Tryton" url="/platforms/python/integrations/tryton" /> | |
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
title: Rust Tracing
3+
description: "Learn about the Rust Tracing integration and how to get performance data for Rust native extensions."
4+
---
5+
6+
`RustTracingIntegration` acts as a bridge between the Sentry Python SDK and Rust's [`tracing` framework](https://tracing.rs/). With this integration, traces that begin in Python can extend into Rust seamlessly.
7+
8+
<Alert level="warning">
9+
10+
This integration assumes that your Rust native extension runs synchronously on the current thread. Emitting tracing data from other threads or Rust code that uses `async`/`.await` may corrupt the current trace.
11+
12+
</Alert>
13+
14+
## Install
15+
16+
`RustTracingIntegration` requires setup in both Python and Rust to work.
17+
18+
### Rust
19+
In your Rust native extension, you'll need three crates as dependencies in `Cargo.toml`:
20+
- [`tracing-subscriber`](https://crates.io/crates/tracing_subscriber)
21+
- [`pyo3`](https://crates.io/crates/pyo3)
22+
- [`pyo3-python-tracing-subscriber`](https://crates.io/crates/pyo3_python_tracing_subscriber)
23+
24+
### Python
25+
In your Python project, you'll need to install the Sentry SDK from PyPI.
26+
```bash
27+
pip install --upgrade sentry-sdk
28+
```
29+
30+
## Configure
31+
32+
As with installing, configuring `RustTracingIntegration` requires some work in both Python and Rust.
33+
34+
### Rust
35+
36+
In your Rust native extension, you need to expose a way for `RustTracingIntegration` to subscribe to `tracing` updates. A simple setup may look like this:
37+
```rust
38+
#[pyfunction]
39+
pub fn initialize_tracing(py_impl: Bound<'_, PyAny>) {
40+
tracing_subscriber::registry()
41+
.with(pyo3_python_tracing_subscriber::PythonCallbackLayerBridge::new(py_impl))
42+
.init();
43+
}
44+
45+
#[pymodule]
46+
fn my_rust_extension(m: &Bound<'_, PyModule>) -> PyResult<()> {
47+
m.add_function(wrap_pyfunction!(initialize_tracing, m)?)?;
48+
49+
Ok(())
50+
}
51+
```
52+
53+
### Python
54+
55+
Create an instance of `RustTracingIntegration` and add it to your list of integrations when initializing the Sentry SDK.
56+
57+
<OnboardingOptionButtons
58+
options={[
59+
'error-monitoring',
60+
'performance',
61+
'profiling',
62+
]}
63+
/>
64+
65+
```python {filename:main.py} {"onboardingOptions": {"performance": "9-11", "profiling": "12-15"}}
66+
import sentry_sdk
67+
from sentry_sdk.integrations.rust_tracing import RustTracingIntegration
68+
69+
import my_rust_extension
70+
71+
async def main():
72+
sentry_sdk.init(
73+
dsn="___PUBLIC_DSN___",
74+
# Set traces_sample_rate to 1.0 to capture 100%
75+
# of transactions for tracing.
76+
traces_sample_rate=1.0,
77+
# Set profiles_sample_rate to 1.0 to profile 100%
78+
# of sampled transactions.
79+
# We recommend adjusting this value in production.
80+
profiles_sample_rate=1.0,
81+
integrations=[
82+
RustTracingIntegration(
83+
"my_rust_extension",
84+
my_rust_extension.initialize_tracing,
85+
include_tracing_fields=True,
86+
),
87+
],
88+
)
89+
90+
# your code goes here.
91+
...
92+
93+
asyncio.run(main())
94+
```
95+
96+
97+
## Verify
98+
99+
A simple way to check if the integration is hooked up correctly is to set a custom `event_type_mapping` and `span_filter` that prints or logs `tracing` event metadata and then call a Python function that uses your Rust native extension.
100+
```python
101+
from sentry_sdk.integrations.rust_tracing import (
102+
default_event_type_mapping,
103+
default_span_filter,
104+
EventTypeMapping,
105+
RustTracingIntegration,
106+
)
107+
108+
import my_rust_extension
109+
110+
def custom_event_type_mapping(metadata: dict) -> EventTypeMapping:
111+
print(metadata)
112+
return default_event_type_mapping(metadata)
113+
114+
def custom_span_filter(metadata: dict) -> bool:
115+
print(metadata)
116+
return default_span_filter(metadata)
117+
118+
sentry_sdk.init(
119+
# ...
120+
integrations=[
121+
RustTracingIntegration(
122+
"my_rust_extension",
123+
my_rust_extension.initialize_tracing,
124+
event_type_mapping=custom_event_type_mapping,
125+
span_filter=custom_span_filter,
126+
),
127+
],
128+
)
129+
```
130+
131+
To see the results on [sentry.io](https://sentry.io), go to the Traces section for your project and search for a Python span that calls a function from your Rust native extension. If the integration is working and the Rust function is instrumented with the Rust `tracing` framework, then the Python span will have a Rust child, and the Rust child may have a whole tree of Rust spans beneath it.
132+
133+
The `pyo3-python-tracing-subscriber` crate has [a working example of a Sentry integration](https://github.com/getsentry/pyo3-python-tracing-subscriber/tree/main/demo).
134+
135+
## Options
136+
137+
`RustTracingIntegration` accepts a few arguments:
138+
- `identifier` (required)
139+
140+
A unique identifier for this native extension. If your project uses more than one Rust native extension, each of them needs its own `RustTracingIntegration`.
141+
142+
- `initializer` (required)
143+
144+
A function from your native extension that `RustTracingIntegration` can call to subscribe to `tracing` events.
145+
146+
See the `initialize_tracing` example in [the _Configure_ section above](#configure)
147+
148+
- `event_type_mapping` (optional)
149+
150+
A function that decides what type of Sentry event to create for a given `tracing` event.
151+
152+
It takes a single argument: a dictionary containing data from [`tracing::Metadata`](https://docs.rs/tracing/latest/tracing/struct.Metadata.html).
153+
154+
It returns a `sentry_sdk.integrations.rust_tracing.EventTypeMapping`.
155+
156+
Uses `sentry_sdk.integrations.rust_tracing.default_event_type_mapping` by default.
157+
158+
- `span_filter` (optional)
159+
160+
A function that decides whether to drop a given `tracing` span.
161+
162+
It takes a single argument: a dictionary containing data from [`tracing::Metadata`](https://docs.rs/tracing/latest/tracing/struct.Metadata.html).
163+
164+
It returns `True` if a span should be processed and `False` if it should be dropped.
165+
166+
Uses `sentry_sdk.integrations.rust_tracing.default_span_filter` by default.
167+
168+
- `include_tracing_fields` (optional)
169+
170+
A boolean controlling whether the values of a `tracing` span's key-value fields will be attached to the corresponding Sentry span.
171+
172+
If it is `None`, this behavior will be controlled by <PlatformLink to="/configuration/options/#send-default-pii">the `send_default_pii` option</PlatformLink> set during SDK initialization. If it is `False`, field values will be redacted on Sentry spans. If it is `True`, field values will be included on Sentry spans.
173+
174+
The default value of this option is `None`.
175+
176+
<Alert level="warning">
177+
178+
When the `tracing::instrument` attribute is applied to a Rust function, `tracing` will set all of the function's arguments as span fields by default. This behavior can cause a function argument that contains sensitive data to unintentionally be sent to Sentry. To avoid that, `include_tracing_fields` by default will defer to the <PlatformLink to="/configuration/options/#send-default-pii">`send_default_pii`</PlatformLink> option which can be set during SDK initialization.
179+
180+
If you want to set `include_tracing_fields` or <PlatformLink to="/configuration/options/#send-default-pii">`send_default_pii`</PlatformLink> to `True`, see our documentation for <PlatformLink to="/data-management/sensitive-data/">managing sensitive data</PlatformLink> for ways to keep sensitive data from leaking.
181+
182+
</Alert>
183+
184+
## Supported Versions
185+
186+
- Python: 3.7+
187+
- Rust: 1.63+

src/components/platformIcon.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ export const PLATFORM_TO_ICON = {
969969
'python-quart': 'quart',
970970
'python-redis': 'redis',
971971
'python-rq': 'redis',
972+
'python-rust_tracing': 'rust',
972973
'python-sanic': 'sanic',
973974
'python-serverless': 'serverless',
974975
'python-starlette': 'starlette',

0 commit comments

Comments
 (0)