Skip to content

fix(dart): Count streamed spans in client reports - #4097

Merged
buenaflor merged 3 commits into
mainfrom
fix/span-client-report-quantity
Oct 30, 2026
Merged

buenaflor merged 3 commits into
mainfrom
fix/span-client-report-quantity

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

📜 Description

DataCategory.fromItemType had no case for the span envelope item type (span streaming / span.v2), so it fell through to DataCategory.unknown. As a result:

  • When a span envelope failed to send (network_error / send_error), it was recorded as 1 outcome with category unknown, not N outcomes with category span.
  • Span envelope items were never dropped by a span rate limit, because RateLimiter._isRetryAfter skips unknown categories. Only __all__ limits applied.

This PR:

  • maps 'span' → DataCategory.span.
  • adds TransportUtils.recordLostItem, which records one dropped envelope item and counts every telemetry item it contains (log_item/log_byte, trace_metric/trace_metric_byte, span via itemCount, and transaction child spans). HttpTransport (through recordLostEvents) and RateLimiter.filter both call it, so there's one copy of this branching instead of two.

💡 Motivation and Context

This aligns with the develop-docs clarification in getsentry/sentry-docs#19854 ("Quantity of Discarded Envelopes" in client-reports spec 1.25.0, and the "Client Reports" section in spans spec 1.1.0): the quantity must be the number of discarded spans, not the number of envelopes or envelope items. Logs and metrics already did this. Spans were the gap.

This only covers the Dart HttpTransport path. On Flutter mobile, envelopes go to the native SDK through FileSystemTransport, so the native SDK records send failures there.

Not in scope: the new spans spec also lists a no_parent_span discard reason, which doesn't exist in DiscardReason yet.

💚 How did you test it?

  • Wrote failing tests first: fromItemType('span'), a span rate limit dropping a 3-span envelope with quantity 3, and a network error on a 3-span envelope recording span quantity 3.
  • dart test in packages/dart (VM): all 1713 tests pass.
  • dart analyze and dart format --set-exit-if-changed are clean with Dart 3.13.5.

📝 Checklist

  • I reviewed submitted code
  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPii is enabled
  • I updated the docs if needed
  • All tests passing
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec
  • No breaking changes

The changes are internal (TransportUtils isn't exported). Behavior change: span rate limits now drop span-streaming envelope items, as the spec requires.

🔮 Next steps

  • Follow-up: add a no_parent_span discard reason and record it.

via Gino Buenaflor.

--

View Junior Session [Sentry]

Map the `span` envelope item type to the `span` data category so
dropped span-streaming envelopes record one outcome per contained
span instead of a single `unknown` outcome. This also makes `span`
rate limits apply to span envelope items.

Per-item recording now lives in `TransportUtils.recordLostItem`,
shared by the HTTP transport and the rate limiter.

Co-Authored-By: Gino Buenaflor <giancarlo.buenaflor@sentry.io>
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Fixes

  • (dart) Count streamed spans in client reports by buenaflor with sentry-junior in #4097
  • (flutter) Use static SwiftPM binaries by philprime and lucas-zimerman in #4118

Dependencies

Deps

  • chore(deps): update Cocoa SDK to v9.32.0 by github-actions in #4128
  • chore(deps): update Native SDK to v0.17.5 by github-actions in #4127
  • chore(deps): update Android SDK to v8.62.0 by github-actions in #4124

Internal Changes

  • (flutter) Use Cocoa internal serializer by philprime, buenaflor and christophaigner in #4100
  • Use dark-mode-aware Sentry logo in READMEs by szokeasaurusrex with sentry-junior in #4123

🤖 This preview updates automatically when you update the PR.

@codecov

codecov Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.80%. Comparing base (f8991b2) to head (e87a082).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4097      +/-   ##
==========================================
- Coverage   88.81%   88.80%   -0.02%     
==========================================
  Files         348      348              
  Lines       12631    12627       -4     
==========================================
- Hits        11218    11213       -5     
- Misses       1413     1414       +1     
Flag Coverage Δ
sentry 88.73% <100.00%> (-0.01%) ⬇️
sentry_dio 97.95% <ø> (ø)
sentry_drift 93.63% <ø> (ø)
sentry_file 64.41% <ø> (ø)
sentry_firebase_remote_config 100.00% <ø> (ø)
sentry_flutter 92.66% <ø> (-0.03%) ⬇️
sentry_grpc 99.11% <ø> (ø)
sentry_hive 76.37% <ø> (ø)
sentry_isar 73.88% <ø> (ø)
sentry_link 22.04% <ø> (ø)
sentry_logging 97.01% <ø> (ø)
sentry_sqflite 88.88% <ø> (ø)
sentry_supabase 97.48% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@buenaflor
buenaflor marked this pull request as ready for review October 29, 2026 03:24
Copilot AI balanced review requested due to automatic review settings October 29, 2026 03:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

There are no active review issues for the streamed-span client-reporting changes.

No open issues 🎉

What changed in this PR

This PR fixes streamed-span client reporting in the Dart SDK’s HTTP transport path, so discarded spans are counted individually and span-specific rate limits apply.

Changes:

  • Maps span envelope items to DataCategory.span.
  • Centralizes dropped-item accounting for transport failures and rate limiting.
  • Adds regression tests for span categorization and three-span discard counts.
File Description
packages/​dart/​test/​transport/​rate_limiter_test.dart Tests span categorization, rate-limit filtering, and discarded-span counts.
packages/​dart/​test/​transport/​http_transport_test.dart Tests discarded-span counts after a network failure.
packages/​dart/​lib/​src/​transport/​transport_utils.dart Adds shared dropped-item accounting using span item counts.
packages/​dart/​lib/​src/​transport/​rate_limiter.dart Reuses shared accounting for rate-limited items.
packages/​dart/​lib/​src/​transport/​data_category.dart Maps the span item type to its client-report category.

Review effort: Balanced

@buenaflor
buenaflor enabled auto-merge (squash) October 30, 2026 00:03
@buenaflor
buenaflor merged commit 7e3e132 into main Oct 30, 2026
135 checks passed
@buenaflor
buenaflor deleted the fix/span-client-report-quantity branch October 30, 2026 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants