Skip to content

feat(tracing): Add user data to tracestate header #3343

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

Conversation

lobsterkatie
Copy link
Member

As the title says...

Specific things to note:

  • User data is included as an object, with the keys id and segment. For now, the id is sent un-hashed (until we can figure out exactly how we want to handle hashing in a way which is repeatable across platforms).
  • The sentry part of the tracestate header is now computed lazily, to increase the chances user data will make it in (since it often isn't know at transaction start time):
    • If a sentry tracestate value is passed in at transaction creation time, as when it's inherited, that value is used and no amount of setting user data (or any other data, for that matter) after the fact will affect it. (This is not a change.)
    • If no value is passed to the constructor, the property remains undefined until it's needed. (This is a change.)
    • The first time it might be needed is to be used in headers on an outgoing request. Therefore, getTraceHeaders is now a get-or-create method with respect to the sentry tracestate value. Once it's been set in that method once, it is immutable. (This is also a change.)
    • The second time it might be needed is for use in envelope headers for transaction events. If no sentry tracestate value is passed to the transaction constructor and no XHR requests are made during the transaction, the transaction will close without a sentry tracestate value. In this case, transaction.finish will compute the value as it's capturing the event. (This, too, is a change.)

@github-actions
Copy link
Contributor

github-actions bot commented Mar 24, 2021

size-limit report

Path Size
@sentry/browser - CDN Bundle (gzipped) 27.03 KB (-0.01% 🔽)
@sentry/browser - Webpack 27.91 KB (0%)
@sentry/react - Webpack 27.95 KB (0%)
@sentry/browser + @sentry/tracing - CDN Bundle (gzipped) 34.8 KB (+0.3% 🔺)

Copy link

@RaduW RaduW left a comment

Choose a reason for hiding this comment

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

From what I can figure out it looks reasonable.
There are a few things I didn't quite understand, see comments, but there is no stopper as far as I'm concerned.

Comment on lines +2 to +3
import { getCurrentHub, Hub } from '@sentry/hub';
import { Primitive, Span as SpanInterface, SpanContext, TraceHeaders, Transaction } from '@sentry/types';
Copy link

Choose a reason for hiding this comment

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

What's going on here ? Doesn't seem to be related to the PR.

Copy link
Member Author

@lobsterkatie lobsterkatie Mar 24, 2021

Choose a reason for hiding this comment

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

It actually is, though. The change here is from importing the type to importing the class. Later on in the file I'm calling Hub.getScope(), a method which exists on the class but isn't in the type, so if I don't make this change, it won't compile. The alternative to doing this is to add the method to the type, which I'm happy to do instead if you think that's better.

Copy link

Choose a reason for hiding this comment

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

Understood, it's probably me (I'm not so familiar with this code) but it further raises the question why we don't have getScope in the interface ( since we do have pushScope, popScope, withScope).

Anyway, not the right place to discuss general architecture of the API.

Comment on lines +115 to +119
// ensure that we have a tracestate to attach to the envelope header
if (!this.metadata.tracestate?.sentry) {
this.metadata.tracestate = { ...this.metadata.tracestate, sentry: this._getNewTracestate() };
}

Copy link

Choose a reason for hiding this comment

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

Nit: I saw that this is not a new thing (it predates this PR) but why do we push tracestate in debug_meta ?
Nobody uses it in Relay from debug_meata (I'm looking for it in the http headers).

If we didn't _getNewTracestate() could become private.

Copy link
Member Author

@lobsterkatie lobsterkatie Mar 24, 2021

Choose a reason for hiding this comment

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

why do we push tracestate in debug_meta ?
Nobody uses it in Relay from debug_meata (I'm looking for it in the http headers).

Because it needs to get through to here somehow, and putting it in debug_meta means that even if it slips through* and makes it to sentry, it won't show up for the user. (Previously the information hitched a ride on a custom tag, and a bug in the code meant that it was showing up for users.)

*If you look a few lines into the linked function, you'll see that in fact it gets pulled out of the eventual event payload. Same with the sampling data.

If we didn't _getNewTracestate() could become private.

Is there any advantage to that over it being protected (which it is currently)?

Copy link

@RaduW RaduW Mar 26, 2021

Choose a reason for hiding this comment

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

Again it was just a nit, but in general I find protected members to be a sign of a messy abstraction. It is something that you think you shouldn't expose ( otherwise you would make it public) but have to expose it "a little" because derived classes need to mess with it.

Comment on lines +66 to +70
/**
* Metadata about the transaction
*/
metadata: TransactionMetadata;

Copy link

Choose a reason for hiding this comment

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

why did we add this ?

Also looking more in detail at TransactionMetadata I understand that traceSampling can be interesting but I can't quite figure out why we pass tracestate since we can figure it out from the headers.

Copy link
Member Author

Choose a reason for hiding this comment

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

why did we add this ?

Because we now need to access it from within the Span class. Since the Transaction class extends the Span class, it imports from './span'. If the Span class also imported the Transaction class (from './transaction'), we'd end up in an import loop. Span therefore has to import Transaction instead from from @sentry/types, which means the type needs to know about the metadata property.

I can't quite figure out why we pass tracestate since we can figure it out from the headers

This is us having figured it out from the headers. The headers are passed to extractTracestateData, and the data then comes through startTransaction to the constructor (for example here.)

@lobsterkatie lobsterkatie merged commit 8e349e7 into kmclb-dynamic-sampling-data-in-envelopes Apr 2, 2021
@lobsterkatie lobsterkatie deleted the kmclb-add-user-to-tracestate branch April 2, 2021 22:39
lobsterkatie added a commit that referenced this pull request Aug 24, 2021
This is the result of rebasing the feature branch for the initial implementation of `tracestate` header handling (which had grown very stale) on top of current `master`. That branch is going to get deleted, so for posterity, it included the following PRs (oldest -> newest):

feat(tracing): Add dynamic sampling correlation context data to envelope header (#3062)
chore(utils): Split browser/node compatibility utils into separate module (#3123)
ref(tracing): Prework for initial `tracestate` implementation (#3242)
feat(tracing): Add `tracestate` header to outgoing requests (#3092)
ref(tracing): Rework tracestate internals to allow for third-party data (#3266)
feat(tracing): Handle incoming tracestate data, allow for third-party data (#3275)
chore(tracing): Various small fixes to first `tracestate` implementation (#3291)
fix(tracing): Use `Request.headers.append` correctly (#3311)
feat(tracing): Add user data to tracestate header (#3343)
chore(various): Small fixes (#3368)
fix(build): Prevent Node's `Buffer` module from being included in browser bundles (#3372)
fix(tracing): Remove undefined tracestate data rather than setting it to `null` (#3373)

More detail in the PR description.
lobsterkatie added a commit that referenced this pull request Aug 30, 2021
This is the result of rebasing the feature branch for the initial implementation of `tracestate` header handling (which had grown very stale) on top of current `master`. That branch is going to get deleted, so for posterity, it included the following PRs (oldest -> newest):

feat(tracing): Add dynamic sampling correlation context data to envelope header (#3062)
chore(utils): Split browser/node compatibility utils into separate module (#3123)
ref(tracing): Prework for initial `tracestate` implementation (#3242)
feat(tracing): Add `tracestate` header to outgoing requests (#3092)
ref(tracing): Rework tracestate internals to allow for third-party data (#3266)
feat(tracing): Handle incoming tracestate data, allow for third-party data (#3275)
chore(tracing): Various small fixes to first `tracestate` implementation (#3291)
fix(tracing): Use `Request.headers.append` correctly (#3311)
feat(tracing): Add user data to tracestate header (#3343)
chore(various): Small fixes (#3368)
fix(build): Prevent Node's `Buffer` module from being included in browser bundles (#3372)
fix(tracing): Remove undefined tracestate data rather than setting it to `null` (#3373)

More detail in the PR description.
lobsterkatie added a commit that referenced this pull request Aug 31, 2021
This is the result of rebasing the feature branch for the initial implementation of `tracestate` header handling (which had grown very stale) on top of current `master`. That branch is going to get deleted, so for posterity, it included the following PRs (oldest -> newest):

feat(tracing): Add dynamic sampling correlation context data to envelope header (#3062)
chore(utils): Split browser/node compatibility utils into separate module (#3123)
ref(tracing): Prework for initial `tracestate` implementation (#3242)
feat(tracing): Add `tracestate` header to outgoing requests (#3092)
ref(tracing): Rework tracestate internals to allow for third-party data (#3266)
feat(tracing): Handle incoming tracestate data, allow for third-party data (#3275)
chore(tracing): Various small fixes to first `tracestate` implementation (#3291)
fix(tracing): Use `Request.headers.append` correctly (#3311)
feat(tracing): Add user data to tracestate header (#3343)
chore(various): Small fixes (#3368)
fix(build): Prevent Node's `Buffer` module from being included in browser bundles (#3372)
fix(tracing): Remove undefined tracestate data rather than setting it to `null` (#3373)

More detail in the PR description.
lobsterkatie added a commit that referenced this pull request Sep 15, 2021
This is the result of rebasing the feature branch for the initial implementation of `tracestate` header handling (which had grown very stale) on top of current `master`. That branch is going to get deleted, so for posterity, it included the following PRs (oldest -> newest):

feat(tracing): Add dynamic sampling correlation context data to envelope header (#3062)
chore(utils): Split browser/node compatibility utils into separate module (#3123)
ref(tracing): Prework for initial `tracestate` implementation (#3242)
feat(tracing): Add `tracestate` header to outgoing requests (#3092)
ref(tracing): Rework tracestate internals to allow for third-party data (#3266)
feat(tracing): Handle incoming tracestate data, allow for third-party data (#3275)
chore(tracing): Various small fixes to first `tracestate` implementation (#3291)
fix(tracing): Use `Request.headers.append` correctly (#3311)
feat(tracing): Add user data to tracestate header (#3343)
chore(various): Small fixes (#3368)
fix(build): Prevent Node's `Buffer` module from being included in browser bundles (#3372)
fix(tracing): Remove undefined tracestate data rather than setting it to `null` (#3373)

More detail in the PR description.
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.

3 participants