How do you use Sentry?
Sentry Self Hosted v25.9.0
SDK version
0.47.0
Steps to reproduce
Summary
The Rust SDK (tested on 0.47.0) sends the old transaction envelope format,
routing data through the ingest-transactions Kafka topic. Self-hosted Sentry 25.x
has migrated performance storage to EAP (eap_items_1_local), and the pipeline
that sets the has_transactions project flag reads exclusively from ingest-spans
(fed by span v2 envelopes). Because the Rust SDK never writes to ingest-spans,
has_transactions is never set, and the Sentry UI permanently shows the onboarding
empty state instead of traces — even though the trace data arrives and is stored
correctly.
Data flow (current Rust SDK)
Rust SDK → transaction envelope
└─► ingest-transactions (Kafka)
└─► ingest-consumer → transactions topic
└─► transactions_group → snuba-items
└─► eap_items_group → eap_items_1_local ✅ (data stored correctly)
ingest-spans (Kafka) — EMPTY for Rust projects
└─► process-spans → buffered-segments — EMPTY
└─► process-segments → set has_transactions ← NEVER RUNS
Expected data flow (what JS/Python SDKs do)
SDK → span v2 envelope (type: "span")
└─► ingest-spans (Kafka)
├─► process-spans → buffered-segments
│ └─► process-segments → has_transactions = True ✅
└─► snuba-eap-items-consumer → eap_items_1_local ✅
Impact
On self-hosted Sentry 25.x, any project using the Rust SDK will:
-
Have project.flags.has_transactions = False permanently
-
Show the performance onboarding screen instead of traces
(the UI gates on this flag before making any API call)
-
Require a manual one-time workaround per project:
from sentry.models.project import Project
p = Project.objects.get(slug='your-project')
p.update(flags=Project.flags.has_transactions.mask | int(p.flags))
Projects using Python or JS SDKs are unaffected as those SDKs already send
span v2 envelopes.
Expected result
Implement the span v2 envelope format in the Rust SDK so spans are sent as:
envelope header: { dsn, sdk }
item header: { "type": "span", "content_type": "application/vnd.sentry.items.span.v2+json" }
payload: [ { trace_id, span_id, name, is_segment: true, ... }, ... ]
Reference: https://develop.sentry.dev/sdk/telemetry/spans/span-protocol/
This is the format already implemented in JS and Python SDKs as part of the
platform-wide transaction→spans migration (tracked internally as SDK-10).
References
Span v2 protocol spec: https://develop.sentry.dev/sdk/telemetry/spans/span-protocol/
Transactions→Spans FAQ: https://sentry.zendesk.com/hc/en-us/articles/40366087871515
Related: RUST-40 (OTel support — different concern but same underlying need)
Actual result
The performance UI at /organizations/{org}/explore/traces/?project={rust-project}
shows the empty onboarding state ("Set Up Tracing") and never queries for traces.
Server logs confirm the UI calls POST /api/0/projects/{org}/{slug}/create-sample-transaction/
(the onboarding "Create Sample Transaction" button) rather than
GET /api/0/organizations/{org}/traces/.
The trace data IS stored correctly in ClickHouse (eap_items_1_local):
- Spans arrive, are processed, and are queryable via the API
GET /api/0/organizations/{org}/traces/?project={id} returns real traces
- The only broken piece is the
project.flags.has_transactions bit, which controls
the UI gate
How do you use Sentry?
Sentry Self Hosted v25.9.0
SDK version
0.47.0
Steps to reproduce
Summary
The Rust SDK (tested on 0.47.0) sends the old transaction envelope format,
routing data through the
ingest-transactionsKafka topic. Self-hosted Sentry 25.xhas migrated performance storage to EAP (
eap_items_1_local), and the pipelinethat sets the
has_transactionsproject flag reads exclusively fromingest-spans(fed by span v2 envelopes). Because the Rust SDK never writes to
ingest-spans,has_transactionsis never set, and the Sentry UI permanently shows the onboardingempty state instead of traces — even though the trace data arrives and is stored
correctly.
Data flow (current Rust SDK)
Rust SDK → transaction envelope
└─► ingest-transactions (Kafka)
└─► ingest-consumer → transactions topic
└─► transactions_group → snuba-items
└─► eap_items_group → eap_items_1_local ✅ (data stored correctly)
ingest-spans (Kafka) — EMPTY for Rust projects
└─► process-spans → buffered-segments — EMPTY
└─► process-segments → set has_transactions ← NEVER RUNS
Expected data flow (what JS/Python SDKs do)
SDK → span v2 envelope (type: "span")
└─► ingest-spans (Kafka)
├─► process-spans → buffered-segments
│ └─► process-segments → has_transactions = True ✅
└─► snuba-eap-items-consumer → eap_items_1_local ✅
Impact
On self-hosted Sentry 25.x, any project using the Rust SDK will:
Have
project.flags.has_transactions = FalsepermanentlyShow the performance onboarding screen instead of traces
(the UI gates on this flag before making any API call)
Require a manual one-time workaround per project:
Projects using Python or JS SDKs are unaffected as those SDKs already send
span v2 envelopes.
Expected result
Implement the span v2 envelope format in the Rust SDK so spans are sent as:
envelope header: { dsn, sdk }
item header: { "type": "span", "content_type": "application/vnd.sentry.items.span.v2+json" }
payload: [ { trace_id, span_id, name, is_segment: true, ... }, ... ]
Reference: https://develop.sentry.dev/sdk/telemetry/spans/span-protocol/
This is the format already implemented in JS and Python SDKs as part of the
platform-wide transaction→spans migration (tracked internally as SDK-10).
References
Span v2 protocol spec: https://develop.sentry.dev/sdk/telemetry/spans/span-protocol/
Transactions→Spans FAQ: https://sentry.zendesk.com/hc/en-us/articles/40366087871515
Related: RUST-40 (OTel support — different concern but same underlying need)
Actual result
The performance UI at
/organizations/{org}/explore/traces/?project={rust-project}shows the empty onboarding state ("Set Up Tracing") and never queries for traces.
Server logs confirm the UI calls
POST /api/0/projects/{org}/{slug}/create-sample-transaction/(the onboarding "Create Sample Transaction" button) rather than
GET /api/0/organizations/{org}/traces/.The trace data IS stored correctly in ClickHouse (
eap_items_1_local):GET /api/0/organizations/{org}/traces/?project={id}returns real tracesproject.flags.has_transactionsbit, which controlsthe UI gate