-
-
Notifications
You must be signed in to change notification settings - Fork 7
Bring beforeSend-like capability to transactions
#19
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| * Start Date: 2022-09-26 | ||
| * RFC Type: feature | ||
| * RFC PR: https://github.com/getsentry/rfcs/pull/19 | ||
|
|
||
| # Summary | ||
|
|
||
| Proposal to make `beforeSend` (or a similar method) work for transactions (and possibly other payload types in the future) in all SDKs. | ||
|
|
||
| # Motivation | ||
|
|
||
| For error events, `beforeSend` allows the user to make whatever changes they want to event data and to filter events however they want, which is useful for solving the cases where our built-in mechanisms for doing so don't correctly handle their particular use case. There is no such hook for transactions. Instead, users have to use `addGlobalEventProcessor` to add an event processor to the scope. This is less than ideal in a few ways: | ||
|
|
||
| - Ease of use (or lack thereof) | ||
| - Nothing about `beforeSend` is obviously errors-only, so users assume it applies everywhere and try to use it for transactions. | ||
| - Users have to learn two different ways to do effectively the same thing. | ||
| - It forces users to write code in two separate places, which leads to potential redundancy if they want to act on any properties shared by error and transaction events. | ||
|
|
||
| - Lack of ultimate control over transaction events | ||
| - Event processors happen in an unspecified order, and there's no guarantee a processor added by a user will run last. This means that an integration, for example, might change event data after the user's last chance to intervene. | ||
|
|
||
| (That last point is not _strictly_ true. As a last resort, a user could create a custom transport or could proxy events through their own servers, but both of those are pretty ugly, cumbersome workarounds.) | ||
|
|
||
| # Background | ||
|
|
||
| When transactions were introduced, the decision was made not to run them through `beforeSend` because they follow a slightly different schema, and therefore had the potential to break any existing `beforeSend` which relies on its input being a certain shape. It's unclear whether a transaction-specific `beforeSend`-type hook was discussed at the time. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I remember correctly, there we good reasons for not calling
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes - from what I recall, it was exactly the reason I listed there, that the schema mis-match had the potential to break people's
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this sentence is inaccurate. We discussed it and most likely the outcome was what you just pointed out:
Could also be, but I can't recall that.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I think we're miscommunicating here, because I believe we actually agree on the history. Let me try to rephrase: I know that back in the day, when tracing was brand new, we discussed sending transactions through Does that make sense?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yep, that makes sense 👍 |
||
|
|
||
| # Supporting Data | ||
|
|
||
| Issues where this has come up: | ||
| - https://github.com/getsentry/sentry-docs/issues/5525 | ||
| - https://github.com/getsentry/sentry-javascript/issues/4723 | ||
| - https://github.com/getsentry/sentry-javascript/issues/5442 | ||
| - https://github.com/getsentry/sentry-python/issues/1226 | ||
|
|
||
| (and I'm sure many others) | ||
|
|
||
| # Options Considered | ||
|
|
||
| _(Revised after preliminary discussion in https://github.com/getsentry/rfcs/pull/19)_ | ||
|
|
||
| ### **Option 1** | ||
|
|
||
| _(Original proposal, demoted to one option of several after discussion)_ | ||
|
|
||
| Add `beforeSendTransaction` to all SDKs, which (as the name implies) would work exactly the same way `beforeSend` does, but would act upon transactions. | ||
|
|
||
| Pros: | ||
| - Not a breaking change, so less pain for customers in the short run. | ||
| - Not a breaking change, so no need to wait for a major release to implement it. | ||
|
|
||
| Cons: | ||
| - Increased API surface. | ||
| - Code that acts on shared event properties (tags, contexts, etc) would need to be duplicated between `beforeSend` and `beforeSendTransaction`. | ||
| - Unclear/non-parallel naming when considered alongside `beforeSend`. (`beforeSendTransaction` is a clear name, but `beforeSend` is not - it really ought to be `beforeSendError`; similar problem to current confusion with `sampleRate` and `tracesSampleRate`.) | ||
| - Future payload types (replays, profiles, etc) would need their own methods. Where does it end? | ||
|
|
||
| ### **Option 2** | ||
|
|
||
| In the next major of each SDK, start sending both errors and transactions through `beforeSend`. | ||
|
|
||
| Pros: | ||
| - `beforeSend` has a seemingly-universally-applicable name, so the most intuitive thing for users is to have it fulfill its implied role and apply universally. | ||
| - Future payload types could be added without introducing new init options/versions of the method. | ||
|
|
||
| Cons: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In Java we have At the moment the signature of Assuming we change the parameter to type An alternative would be to have two parameters that are |
||
| - Potentially breaking change for everyone, even people not using tracing, because old assumptions about `beforeSend` input schema would no longer hold. (We could maybe work around this by just surrounding our `beforeSend` call with a `try-catch` and returning the event untouched if things go sideways.) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO another con is that users might end up checking the type of the payload and then casting it to different payload types.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If they did this, would it break downstream processing in the SDK?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it would, but IMO this is an unappealing API. |
||
|
|
||
| ### **Option 3** | ||
|
|
||
| Like option 2, except `beforeSend` doesn't change and instead we create a new universal method to take its place. | ||
|
|
||
| Pros: | ||
| - Not a breaking change, so less pain for customers in the short run. | ||
| - Not a breaking change, so no need to wait for a major release to implement it. | ||
|
|
||
| Cons: | ||
| - What would we call it? The most logical name given other option names (`beforeBreadcrumb`, `beforeNavigate`, etc) is already taken. | ||
| - What would happen to `beforeSend`? Either we'd eventually either: 1) deprecate and remove it, which just kicks the breaking-change can down the road, or 2) keep it around in perpetutity, which isn't great either, because it would probably continue to confuse people (both by providing a less-functional way to do what the new method does and by _still_ not being named `beforeSendError`). | ||
|
Comment on lines
+77
to
+78
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these are not cons; these are problems to solve. I think having one method called before sending anything makes sense. Alongside adding the universal method, we could also have fine-grained methods. That would be Option 5, then. Option 5Add a new universal
Option 6Make
|
||
|
|
||
| ### **Option 4** | ||
|
|
||
| _(Listed for the sake of completeness, and not a bad idea in and of itself, but by general consensus probably not the right option here)_ | ||
|
|
||
| Implement lifecycle hooks for transactions (and possibly replays, profiles, etc in the future) | ||
|
|
||
| Pros: | ||
| - Granular control | ||
| - Depending on how we do it, might line us up with OTel. | ||
|
|
||
| Cons: | ||
| - Significantly bigger footprint than other options, not only in terms of work to build it but also documentation, support, and bundle size. | ||
| - Would act primarily on `Transaction` objects whereas we're trying to match `beforeSend`'s ability to act on finalized events. | ||
|
|
||
| # Drawbacks | ||
|
|
||
| Compared to doing nothing, the only drawbacks to any of the above options are the time and effort it will take to implement and document the changes. (In other words, the idea of giving people `beforeSend`-like powers over transactions doesn't have any notable drawbacks on its own.) | ||
|
|
||
| # Unresolved questions | ||
|
|
||
| - If we go with the `beforeSendTransaction` option, what all should go in the hint? Are we happy with the `beforeSendTransaction` name, or are there better alternatives? | ||
| - If we go with a new universal method, what should we call it? What should happen to `beforeSend` afterwards? | ||
| - Once we do this, should we deprecate `addGlobalEventProcessor` as a public API method? (Not inherently a part of this change, but something that was spoken of in the past but then backed away from because event processors were the workaround to the problem this RFC is trying to solve.) | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To "Event processors happen in an unspecified order": This was also one thing we observed in Python. The user wanted to add an event processor to filter transactions based on something in the request. But our internal integration added this request to the event also with an event processor.
The users event processor ran before the integrations event processor so there was no request in the event (or the hint? cant remember) so it was impossible to filter the transactions in an event processor.
Proposal:
We could add special
user_event_processors(or whatever the name) and those event processors are run AFTER all the currently available event processors. To make sure all the SDK internal processing has been done and now the user can do stuff with the event.(One down side: "all the SDK internal processing" also means the event could have been dropped/sampled already)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a good point, @antonpirker, but I think that is a different discussion.