Skip to content

Conversation

giortzisg
Copy link
Contributor

@giortzisg giortzisg commented Sep 24, 2025

Description

Create the new transport that accepts envelopes and not events. For now only the implementation for the new transport is added, without deprecating the old one. The PR also includes some misc changes:

  • creating an envelope convertible interface, to accept a generic type of events/logs/transactions, etc..
  • moving the dsn internally under the protocol folder and re exporting everything on the top level to avoid cyclic imports when using the new transport.

Issues


Note

Introduce envelope-first Sync/Async HTTP transports, centralize DSN and envelope types under internal/protocol, and adapt SDK to use them with minimal API surface changes.

  • Transport (new):
    • Add internal/http transports: AsyncTransport and SyncTransport that send protocol.Envelopes, with queueing, flush/close, rate limiting, proxy/TLS config, headers, and keep-alive handling.
  • Protocol (new):
    • Add internal/protocol: Dsn, Envelope (+ items, header), SdkInfo, and interfaces (EnvelopeConvertible, TelemetryTransport).
    • Provide DSN parsing, request headers, API URL, JSON marshal/unmarshal.
  • SDK integration/refactor:
    • Wrap and re-export Dsn and DsnParseError in top-level sentry; NewDsn delegates to protocol; RequestHeaders() uses SDK version; minor typo fix in comment.
    • Add Event.ToEnvelope/ToEnvelopeWithTime; include DSC trace info and attachments; fallback JSON marshal path preserved.
    • Update DynamicSamplingContext and transport.go to use DSN getters (GetPublicKey, etc.) and scheme constants from protocol in NewRequest.
  • Tests:
    • Add comprehensive tests for protocol DSN/envelope, new transports (queueing, flush, rate limits, errors, keep-alive, proxies/TLS, concurrency, goroutine leaks), and wrapper behavior; expand request and event tests.

Written by Cursor Bugbot for commit 1ed184b. This will update automatically on new commits. Configure here.

Copy link

linear bot commented Sep 24, 2025

Copy link

codecov bot commented Sep 24, 2025

Codecov Report

❌ Patch coverage is 84.61538% with 104 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.64%. Comparing base (193c8ad) to head (d61df59).

Files with missing lines Patch % Lines
internal/http/transport.go 84.22% 40 Missing and 16 partials ⚠️
internal/protocol/envelope.go 63.73% 22 Missing and 11 partials ⚠️
interfaces.go 87.93% 5 Missing and 2 partials ⚠️
transport.go 86.11% 2 Missing and 3 partials ⚠️
internal/protocol/dsn.go 97.69% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@                    Coverage Diff                     @@
##           feat/transport-buffers    #1094      +/-   ##
==========================================================
- Coverage                   86.98%   86.64%   -0.35%     
==========================================================
  Files                          57       60       +3     
  Lines                        6356     6894     +538     
==========================================================
+ Hits                         5529     5973     +444     
- Misses                        675      739      +64     
- Partials                      152      182      +30     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 85 to 87
return &tls.Config{
RootCAs: options.CaCerts,
}
Copy link

@semgrep-code-getsentry semgrep-code-getsentry bot Sep 26, 2025

Choose a reason for hiding this comment

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

MinVersion is missing from this TLS configuration. By default, as of Go 1.22, TLS 1.2 is currently used as the minimum. General purpose web applications should default to TLS 1.3 with all other protocols disabled. Only where it is known that a web server must support legacy clients with unsupported an insecure browsers (such as Internet Explorer 10), it may be necessary to enable TLS 1.0 to provide support. Add `MinVersion: tls.VersionTLS13' to the TLS configuration to bump the minimum version to TLS 1.3.

🧼 Fixed in commit 871ade0 🧼

Copy link
Member

Choose a reason for hiding this comment

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

can we address this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since go uses tls1.2 we should be good to this as the min version. We already inherit the min version of the runtime anyways.

@giortzisg giortzisg force-pushed the feat/transport-envelope branch from 3ce9dee to 4228142 Compare September 29, 2025 14:02
@giortzisg giortzisg marked this pull request as ready for review September 29, 2025 14:27
cursor[bot]

This comment was marked as outdated.

Copy link
Member

@sl0thentr0py sl0thentr0py left a comment

Choose a reason for hiding this comment

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

ideally we'd also abstract the older event types as envelope items, but I'll leave it upto you if you want to do that now or separately later

Copy link
Member

@lcian lcian left a comment

Choose a reason for hiding this comment

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

Left some mostly minor comments, looks good overall. Haven't looked at the tests yet.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

func (t *AsyncTransport) SendEvent(event protocol.EnvelopeConvertible) {
envelope, err := event.ToEnvelope(t.dsn)
if err != nil {
debuglog.Printf("Failed to convert to envelope: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
debuglog.Printf("Failed to convert to envelope: %v", err)
debuglog.Printf("Failed to convert to envelope: %s", err.Error())

using %v is heavier performance-wise than %s

Copy link
Contributor Author

@giortzisg giortzisg Oct 10, 2025

Choose a reason for hiding this comment

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

for errors I think this doesn't really apply, both just call err.Error() IIRC.

}

if err := t.SendEnvelope(envelope); err != nil {
debuglog.Printf("Error sending the envelope: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
debuglog.Printf("Error sending the envelope: %v", err)
debuglog.Printf("Error sending the envelope: %s", err.Error())

same goes with this

// Parse
parsedURL, err := url.Parse(rawURL)
if err != nil {
return nil, &DsnParseError{fmt.Sprintf("invalid url: %v", err)}
Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't we do something like this?

Suggested change
return nil, &DsnParseError{fmt.Sprintf("invalid url: %v", err)}
return nil, &DsnParseError{fmt.Errorf("invalid url: %w", err)}

That way, we can trace what the actual inner error is.

This would modify DsnParseError to:

type DsnParseError struct {
	Message error
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't really want to break the signature for message, since it doesn't really give that much value.

// PublicKey
publicKey := parsedURL.User.Username()
if publicKey == "" {
return nil, &DsnParseError{"empty username"}
Copy link
Contributor

Choose a reason for hiding this comment

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

username is confusing, users only understand "public key" and "project id"

Suggested change
return nil, &DsnParseError{"empty username"}
return nil, &DsnParseError{"empty public key"}

if dsn.secretKey != "" {
url += fmt.Sprintf(":%s", dsn.secretKey)
}
url += fmt.Sprintf("@%s", dsn.host)
Copy link
Contributor

Choose a reason for hiding this comment

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

Annoying request, but: What about self-hosted users that uses private IPv6 address on their DSN? 😀

Copy link
Member

@lcian lcian Oct 9, 2025

Choose a reason for hiding this comment

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

Why is this problematic for IPv6?

Copy link
Contributor

Choose a reason for hiding this comment

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

For IPv6, you would need to enclose it within [] brackets. Or maybe just create a test case for this one.

@giortzisg giortzisg changed the base branch from master to feat/transport-buffers October 9, 2025 15:04
@giortzisg giortzisg changed the base branch from feat/transport-buffers to master October 10, 2025 08:22
@giortzisg giortzisg changed the base branch from master to feat/transport-buffers October 10, 2025 09:07
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.

Create new transport that accepts envelopes

5 participants