feat: Make transport channel capacity configurable#1040
feat: Make transport channel capacity configurable#1040mvanhorn wants to merge 5 commits intogetsentry:masterfrom
Conversation
Add `transport_channel_capacity` field to `ClientOptions` that controls the bounded sync channel size used by the transport thread. Defaults to 30 (preserving current behavior). Users in high-throughput scenarios can increase this to reduce the chance of dropped envelopes. Closes getsentry#994 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #1040 +/- ##
==========================================
- Coverage 73.81% 73.69% -0.12%
==========================================
Files 64 65 +1
Lines 7538 7577 +39
==========================================
+ Hits 5564 5584 +20
- Misses 1974 1993 +19 |
|
Hi @mvanhorn, thanks for the contribution! Before I proceed to a full review, please address the CI failures and the AI review agent comments. If any of the AI review comments are inaccurate, please comment on them and mark as resolved. Thanks! |
- Add transport_channel_capacity to manual Debug implementation - Clamp channel capacity to minimum of 1 to prevent rendezvous channel from silently dropping envelopes via try_send - Run cargo fmt to fix lint CI failure
|
Addressed in 9c8f904:
|
szokeasaurusrex
left a comment
There was a problem hiding this comment.
Thanks again for the contribution. I think we should revise the public API shape to avoid public API breakages before merging this change.
The current implementation introduces public API breakage by:
- adding a new public field to
ClientOptions - changing the signatures of the public transport thread constructors
I would like to avoid those breakages here and instead expose this as additive API:
- add additive
with_capacity(...)constructors on the public transport thread types, i.e.StdTransportThread::with_capacity(send, channel_capacity)andTokioTransportThread::with_capacity(send, channel_capacity) - keep the existing
new(...)signatures unchanged, but make those constructors delegate towith_capacity(..., 30) - add transport-specific constructors such as
ReqwestHttpTransport::with_channel_capacity(options, channel_capacity)(and similarly forcurlandureq), which would use those newwith_capacity(...)thread constructors internally - document use through
ClientOptions.transport
That still gives users a way to override the transport queue capacity via the existing TransportFactory mechanism, without changing ClientOptions yet.
For example, initializing the SDK with a custom capacity could look like this:
let opts = ClientOptions {
transport: Some(Arc::new(move |opts| {
Arc::new(ReqwestHttpTransport::with_channel_capacity(opts, 256))
})),
..Default::default()
};If you are open to it, please refactor the PR in that direction. If not, let me know and I can take it over as a follow-up.
…el_capacity Per review: avoid public API breakages in ClientOptions and the transport constructors. Replace the 'transport_channel_capacity: usize' field and the changed TransportThread/transport constructor signatures with purely additive APIs: - TransportThread::new(send) restored to original signature, delegates to with_capacity(send, 30). TransportThread::with_capacity(send, capacity) is the new entry point for custom capacity. - Same pattern for tokio_thread::TransportThread. - ReqwestHttpTransport/CurlHttpTransport/UreqHttpTransport gain with_channel_capacity(options, capacity). Existing new/with_client/ with_agent keep the default capacity of 30. - Remove transport_channel_capacity from ClientOptions (field, Default, and Debug impl). Users that need to override capacity configure it via ClientOptions.transport with a factory returning the desired transport, e.g. Arc::new(move |opts| Arc::new(ReqwestHttpTransport::with_channel_capacity(opts, 256))).
|
Thanks for the direction @szokeasaurusrex. Refactored to the additive shape you described in fbff3ea:
Your example works unchanged: let opts = ClientOptions {
transport: Some(Arc::new(move |opts| {
Arc::new(ReqwestHttpTransport::with_channel_capacity(opts, 256))
})),
..Default::default()
};
|
|
|
||
| /// Creates a new Transport that uses the specified [`CurlClient`]. | ||
| pub fn with_client(options: &ClientOptions, client: CurlClient) -> Self { | ||
| Self::new_internal(options, Some(client)) | ||
| Self::new_internal(options, Some(client), 30) |
There was a problem hiding this comment.
Bug: The transport_channel_capacity field is missing from ClientOptions. Transports default to a hardcoded capacity of 30, ignoring any user-provided value on the options struct.
Severity: HIGH
Suggested Fix
Add the transport_channel_capacity: Option<usize> field to the ClientOptions struct. In the DefaultTransportFactory and other transport creation logic, read this value from the options and pass it to the transport's internal constructor, falling back to the default of 30 if it's not set. This will align the implementation with the documented feature.
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: sentry/src/transports/curl.rs#L23-L26
Potential issue: The feature to configure transport channel capacity via `ClientOptions`
is not implemented as described. The `transport_channel_capacity` field is missing from
the `ClientOptions` struct. As a result, the default transport factory and individual
transport constructors (`CurlHttpTransport`, `ReqwestHttpTransport`,
`UreqHttpTransport`) all use a hardcoded channel capacity of 30. Users attempting to set
this value on `ClientOptions` will find it has no effect. The only way to set a custom
capacity is to manually construct a transport using the new `with_channel_capacity()`
methods, which bypasses the standard client initialization path. This is problematic for
high-throughput use cases where a larger capacity is needed to prevent event drops.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fbff3ea. Configure here.
| /// Creates a new Transport. | ||
| pub fn new(options: &ClientOptions) -> Self { | ||
| Self::new_internal(options, None) | ||
| Self::new_internal(options, None, 30) |
There was a problem hiding this comment.
Transport capacity not read from ClientOptions, feature non-functional
High Severity
The new() methods in all three transports hardcode 30 instead of reading from options. Additionally, transport_channel_capacity was never actually added to ClientOptions (the field does not exist). The DefaultTransportFactory::create_transport calls HttpTransport::new(options), which passes the hardcoded 30 to new_internal. This makes the entire feature non-functional — users have no way to configure the channel capacity through the standard ClientOptions API as the PR intends.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit fbff3ea. Configure here.


Summary
Adds a
transport_channel_capacityfield toClientOptionsso users can tune the bounded channel size used by the transport thread. The default remains 30, preserving existing behavior.Why this matters
In high-throughput scenarios (many transactions with single spans each), the hardcoded capacity of 30 can saturate quickly, leading to dropped envelopes. This was identified in #923 and tracked in #994. Making it configurable lets users trade memory for reliability based on their workload.
Changes
sentry-core/src/clientoptions.rs: Addedtransport_channel_capacity: usizefield (default: 30)sentry/src/transports/thread.rs: Acceptchannel_capacityparameter inTransportThread::newsentry/src/transports/tokio_thread.rs: Same change for the async transport variantsentry/src/transports/curl.rs: Passoptions.transport_channel_capacitytoTransportThread::newsentry/src/transports/reqwest.rs: Samesentry/src/transports/ureq.rs: SameTesting
cargo checkpasses across the full workspaceCloses #994
This contribution was developed with AI assistance (Claude Code).