Skip to content

Traces not showing up on self-hosted 25.9.0 when the SDK sends transactions #4278

@gravityvi

Description

@gravityvi

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:

  1. Have project.flags.has_transactions = False permanently

  2. Show the performance onboarding screen instead of traces
    (the UI gates on this flag before making any API call)

  3. 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

Metadata

Metadata

Assignees

No one assigned
    No fields configured for issues without a type.

    Projects

    Status

    No status

    Status

    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions