Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Send transactions in envelopes #2553

Merged
merged 6 commits into from
May 11, 2020

Conversation

rhcarvalho
Copy link
Contributor

@rhcarvalho rhcarvalho commented Apr 22, 2020

The new Envelope endpoint and format is what we want to use for transactions going forward.

Apart from transactions as Envelopes, we unify how @sentry/browser and @sentry/node authenticate requests for ease of maintenance. Now all requests include the public key as a query string.

@rhcarvalho
Copy link
Contributor Author

This is crude, but wanted to get the ball rolling early.

@getsentry/team-webplatform

@rhcarvalho rhcarvalho force-pushed the transactions-in-envelopes branch 2 times, most recently from eb8eebf to c8cb2c3 Compare April 23, 2020 12:07
@rhcarvalho rhcarvalho force-pushed the transactions-in-envelopes branch 2 times, most recently from 6400b6e to cd3045f Compare April 28, 2020 22:27
const headers = {
...this._api.getRequestHeaders(SDK_NAME, SDK_VERSION),
// The auth headers are not included because auth is done via query string to match @sentry/browser.
//...this._api.getRequestHeaders(SDK_NAME, SDK_VERSION)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a proposition. Without it, this._api.getRequestHeaders needs to know that the Content-Type header is not always application/json anymore, but depends on the event type (error != transaction).

const { hostname, pathname: path, port, protocol } = addr;
const { hostname, port, protocol } = url;
// See https://github.com/nodejs/node/blob/38146e717fed2fabe3aacb6540d839475e0ce1c6/lib/internal/url.js#L1268-L1290
const path = `${url.pathname || ''}${url.search || ''}`;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The helper in node includes the query string in the path, and we should too -- otherwise we'd miss the auth info.

@@ -17,29 +17,54 @@ export class API {
return this._dsnObject;
}

/** Returns a string with auth headers in the url to the store endpoint. */
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was the documentation of getStoreEndpoint! Fixed, it does not include auth.

@@ -5,15 +5,19 @@ import { PromiseBuffer, SentryError } from '@sentry/utils';
/** Base Transport class implementation */
export abstract class BaseTransport implements Transport {
/**
* @inheritDoc
* @deprecated
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This depends on whether a single transport will eventually have to deal with multiple endpoints like now, or whether we'll have independent transports, each having a fixed target endpoint URL.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should stick with one transport with multiple methods for getting url. Although I'm not sure if we should deprecate this attribute just yet, as we are not using envelopes for errors.

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'm not sure if we should deprecate this attribute just yet, as we are not using envelopes for errors.

The transport now always use the _api attribute to fetch the appropriate endpoint. url is only accessed in tests and possibly user code (e.g. custom transport).

/** Returns an object that can be used in request headers. */
/** Returns an object that can be used in request headers.
*
* @deprecated in favor of `getStoreEndpointWithUrlEncodedAuth` and `getEnvelopeEndpointWithUrlEncodedAuth`.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

getRequestHeaders as-is is problematic now because the headers depend on the event type.

@rhcarvalho rhcarvalho marked this pull request as ready for review April 28, 2020 22:40
@rhcarvalho rhcarvalho requested a review from kamilogorek as a code owner April 28, 2020 22:40
@rhcarvalho rhcarvalho force-pushed the transactions-in-envelopes branch 2 times, most recently from e1bbb70 to 76c8de0 Compare April 28, 2020 22:59
@rhcarvalho
Copy link
Contributor Author

@sentry/browser tests need some love, "AssertionError: expected false to equal true" is not helpful.

image

@rhcarvalho rhcarvalho force-pushed the transactions-in-envelopes branch 2 times, most recently from 193f0ed to 15c0c69 Compare April 29, 2020 12:46
expect(options.headers['X-Sentry-Auth']).toContain('sentry_key');
// expect(options.headers['X-Sentry-Auth']).toContain('sentry_version');
// expect(options.headers['X-Sentry-Auth']).toContain('sentry_client');
// expect(options.headers['X-Sentry-Auth']).toContain('sentry_key');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we're okay with sending auth via query string in node, then we can get rid of these lines.

The downside of auth in the query string is increased likelihood of having the "public key" part of the DSN exposed in logs, etc. Since this is more like "identification" then real "authentication", I believe it is not a huge concern, while allowing us to have simpler code.

@rhcarvalho rhcarvalho changed the title [WIP] feat: Send transactions in envelopes feat: Send transactions in envelopes Apr 30, 2020
@rhcarvalho rhcarvalho force-pushed the transactions-in-envelopes branch from 5a8a92b to 3886e5f Compare May 7, 2020 10:45
@rhcarvalho
Copy link
Contributor Author

rhcarvalho commented May 7, 2020

Linter error refers to a file that was not changed in this PR https://travis-ci.com/github/getsentry/sentry-javascript/jobs/329385512#L375,
packages/browser/src/integrations/trycatch.ts changed in #2570 where the linter run was green 😕

update: fixing that file in #2574

@rhcarvalho rhcarvalho requested a review from kamilogorek May 7, 2020 11:52
expect(options.headers['X-Sentry-Auth']).toContain('sentry_version');
expect(options.headers['X-Sentry-Auth']).toContain('sentry_client');
expect(options.headers['X-Sentry-Auth']).toContain('sentry_key');
expect(options.headers).not.toContain('X-Sentry-Auth'); // auth is part of the query string
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please note this change. In order to reuse code between browser and node, we always send auth as part of the query string (and never send sentry_client anymore -- full SDK info is in the event payload).

@rhcarvalho rhcarvalho requested a review from HazAT May 7, 2020 13:40
@rhcarvalho rhcarvalho force-pushed the transactions-in-envelopes branch from ab264dc to c40c043 Compare May 7, 2020 13:41
kamilogorek and others added 5 commits May 8, 2020 18:27
The new Envelope endpoint and format is what we want to use for
transactions going forward.
… request

feat: Set outgoing request Content-Type to ''

Sentry's Relay server expects envelopes to have
  Content-Type: application/x-sentry-envelope
however, that header would cause CORS preflight requests that we want to
avoid.

If we don't set the Content-Type header, browsers fill it in with
text/plain. We prefer sending an empty string than setting an incorrect
Content-Type.

Relay accepts the empty string and treats the body as an envelope.
@rhcarvalho rhcarvalho force-pushed the transactions-in-envelopes branch from c40c043 to b0339da Compare May 8, 2020 16:27
Docs moved, here's the new location.
@rhcarvalho
Copy link
Contributor Author

One down side of this is the reduced debuggability and redundant information in the payload.

Transaction in Envelope 📨

image

  • Browsers don’t know how to prettify the long line of the event JSON;
  • "event_id":"thirty-two-bytes" appears twice in the request body;
  • "type":"transaction" appears twice too; and
  • "sent_at" is the same as the sentry_timestamp part of the authentication header (which we don't send at the moment).

Error Event sent to /store/

image

Copy link
Member

@HazAT HazAT left a comment

Choose a reason for hiding this comment

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

👍

Next item on the menu, category-based rate limiting.

@rhcarvalho rhcarvalho merged commit 8958f61 into getsentry:master May 11, 2020
@rhcarvalho rhcarvalho deleted the transactions-in-envelopes branch May 11, 2020 11:35
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.

None yet

3 participants